From 9fa30c5c20059c40eafbbb6fa249be8fd133286b Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Fri, 6 Jan 2017 17:24:02 +0100 Subject: [PATCH] Handle error cases in IMDN notifications. --- coreapi/chat.c | 73 ++++++++++++++++-------- coreapi/error_info.c | 77 +++++++++++++------------ coreapi/private.h | 2 +- include/linphone/error_info.h | 9 ++- share/xml/Makefile.am | 2 +- share/xml/imdn.xsd | 16 ++++++ tester/message_tester.c | 103 +++++++++++++++++++++++++++++++--- 7 files changed, 211 insertions(+), 71 deletions(-) create mode 100644 share/xml/imdn.xsd diff --git a/coreapi/chat.c b/coreapi/chat.c index 00f2b67fe..a484763b8 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -481,10 +481,14 @@ void linphone_chat_message_update_state(LinphoneChatMessage *msg, LinphoneChatMe linphone_chat_message_store_state(msg); if (msg->state == LinphoneChatMessageStateDelivered || msg->state == LinphoneChatMessageStateNotDelivered) { - // msg is not transient anymore, we can remove it from our transient list and unref it - msg->chat_room->transient_messages = bctbx_list_remove(msg->chat_room->transient_messages, msg); - linphone_chat_room_add_weak_message(msg->chat_room, msg); - linphone_chat_message_unref(msg); + if (bctbx_list_find(msg->chat_room->transient_messages, msg) != NULL) { + // msg is not transient anymore, we can remove it from our transient list and unref it + msg->chat_room->transient_messages = bctbx_list_remove(msg->chat_room->transient_messages, msg); + linphone_chat_room_add_weak_message(msg->chat_room, msg); + linphone_chat_message_unref(msg); + } else { + // msg has already been removed from the transient messages, do nothing. */ + } } } @@ -500,7 +504,7 @@ void linphone_chat_room_message_received(LinphoneChatRoom *cr, LinphoneCore *lc, linphone_core_notify_message_received(lc, cr, msg); cr->remote_is_composing = LinphoneIsComposingIdle; linphone_core_notify_is_composing_received(cr->lc, cr); - linphone_chat_message_send_delivery_notification(msg); + linphone_chat_message_send_delivery_notification(msg, LinphoneReasonNone); } LinphoneReason linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *sal_msg) { @@ -554,6 +558,7 @@ LinphoneReason linphone_core_message_received(LinphoneCore *lc, SalOp *op, const if (retval > 0) { reason = linphone_error_code_to_reason(retval); + linphone_chat_message_send_delivery_notification(msg, reason); goto end; } @@ -806,22 +811,24 @@ static void process_imdn(LinphoneChatRoom *cr, xmlparsing_context_t *xml_ctx) { delivery_status_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, xpath_str); snprintf(xpath_str, sizeof(xpath_str), "%s[1]/imdn:display-notification/imdn:status", imdn_prefix); display_status_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, xpath_str); - if (delivery_status_object != NULL) { + if ((delivery_status_object != NULL) && (linphone_im_notif_policy_get_recv_imdn_delivered(policy) == TRUE)) { if ((delivery_status_object->nodesetval != NULL) && (delivery_status_object->nodesetval->nodeNr >= 1)) { xmlNodePtr node = delivery_status_object->nodesetval->nodeTab[0]; - if ((node->children != NULL) && (node->children->name != NULL) && (strcmp((const char *)node->children->name, "delivered") == 0)) { - if (linphone_im_notif_policy_get_recv_imdn_delivered(policy) == TRUE) { + if ((node->children != NULL) && (node->children->name != NULL)) { + 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(delivery_status_object); } - if (display_status_object != NULL) { + if ((display_status_object != NULL) && (linphone_im_notif_policy_get_recv_imdn_displayed(policy) == TRUE)) { if ((display_status_object->nodesetval != NULL) && (display_status_object->nodesetval->nodeNr >= 1)) { xmlNodePtr node = display_status_object->nodesetval->nodeTab[0]; - if ((node->children != NULL) && (node->children->name != NULL) && (strcmp((const char *)node->children->name, "displayed") == 0)) { - if (linphone_im_notif_policy_get_recv_imdn_displayed(policy) == TRUE) { + if ((node->children != NULL) && (node->children->name != NULL)) { + if (strcmp((const char *)node->children->name, "displayed") == 0) { linphone_chat_message_update_state(cm, LinphoneChatMessageStateDisplayed); } } @@ -1027,7 +1034,7 @@ enum ImdnType { ImdnTypeDisplay }; -static char *linphone_chat_message_create_imdn_xml(LinphoneChatMessage *cm, enum ImdnType imdn_type) { +static char *linphone_chat_message_create_imdn_xml(LinphoneChatMessage *cm, enum ImdnType imdn_type, LinphoneReason reason) { xmlBufferPtr buf; xmlTextWriterPtr writer; int err; @@ -1051,6 +1058,9 @@ static char *linphone_chat_message_create_imdn_xml(LinphoneChatMessage *cm, enum err = xmlTextWriterStartElementNS(writer, NULL, (const xmlChar *)"imdn", (const xmlChar *)"urn:ietf:params:xml:ns:imdn"); } + if ((err >= 0) && (reason != LinphoneReasonNone)) { + err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xmlns", (const xmlChar *)"linphoneimdn", NULL, (const xmlChar *)"http://www.linphone.org/xsds/imdn.xsd"); + } if (err >= 0) { err = xmlTextWriterWriteElement(writer, (const xmlChar *)"message-id", (const xmlChar *)linphone_chat_message_get_message_id(cm)); } @@ -1068,16 +1078,34 @@ static char *linphone_chat_message_create_imdn_xml(LinphoneChatMessage *cm, enum err = xmlTextWriterStartElement(writer, (const xmlChar *)"status"); } if (err >= 0) { - if (imdn_type == ImdnTypeDelivery) { - err = xmlTextWriterStartElement(writer, (const xmlChar *)"delivered"); + if (reason == LinphoneReasonNone) { + if (imdn_type == ImdnTypeDelivery) { + err = xmlTextWriterStartElement(writer, (const xmlChar *)"delivered"); + } else { + err = xmlTextWriterStartElement(writer, (const xmlChar *)"displayed"); + } } else { - err = xmlTextWriterStartElement(writer, (const xmlChar *)"displayed"); + err = xmlTextWriterStartElement(writer, (const xmlChar *)"error"); } } if (err >= 0) { - /* Close the "delivered" or "displayed" element. */ + /* Close the "delivered", "displayed" or "error" element. */ err = xmlTextWriterEndElement(writer); } + if ((err >= 0) && (reason != LinphoneReasonNone)) { + err = xmlTextWriterStartElementNS(writer, (const xmlChar *)"linphoneimdn", (const xmlChar *)"reason", NULL); + if (err >= 0) { + char codestr[16]; + snprintf(codestr, 16, "%d", linphone_reason_to_error_code(reason)); + err = xmlTextWriterWriteAttribute(writer, (const xmlChar *)"code", (const xmlChar *)codestr); + } + if (err >= 0) { + err = xmlTextWriterWriteString(writer, (const xmlChar *)linphone_reason_to_string(reason)); + } + if (err >= 0) { + err = xmlTextWriterEndElement(writer); + } + } if (err >= 0) { /* Close the "status" element. */ err = xmlTextWriterEndElement(writer); @@ -1103,7 +1131,7 @@ static char *linphone_chat_message_create_imdn_xml(LinphoneChatMessage *cm, enum return content; } -static void linphone_chat_message_send_imdn(LinphoneChatMessage *cm, enum ImdnType imdn_type) { +static void linphone_chat_message_send_imdn(LinphoneChatMessage *cm, enum ImdnType imdn_type, LinphoneReason reason) { SalOp *op = NULL; const char *identity = NULL; char *content = NULL; @@ -1121,7 +1149,7 @@ static void linphone_chat_message_send_imdn(LinphoneChatMessage *cm, enum ImdnTy linphone_configure_op(cr->lc, op, cr->peer_url, NULL, lp_config_get_int(cr->lc->config, "sip", "chat_msg_with_contact", 0)); - content = linphone_chat_message_create_imdn_xml(cm, imdn_type); + content = linphone_chat_message_create_imdn_xml(cm, imdn_type, reason); if (content != NULL) { int retval = -1; LinphoneAddress *from_addr = linphone_address_new(identity); @@ -1131,7 +1159,8 @@ static void linphone_chat_message_send_imdn(LinphoneChatMessage *cm, enum ImdnTy linphone_chat_message_set_to_address(msg, to_addr); msg->content_type = ms_strdup("message/imdn+xml"); - if (imee) { + /* Do not try to encrypt the notification when it is reporting an error (maybe it should be bypassed only for some reasons). */ + if (imee && (reason == LinphoneReasonNone)) { 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); if (cb_process_outgoing_message) { @@ -1151,12 +1180,12 @@ static void linphone_chat_message_send_imdn(LinphoneChatMessage *cm, enum ImdnTy sal_op_unref(op); } -void linphone_chat_message_send_delivery_notification(LinphoneChatMessage *cm) { +void linphone_chat_message_send_delivery_notification(LinphoneChatMessage *cm, LinphoneReason reason) { LinphoneChatRoom *cr = linphone_chat_message_get_chat_room(cm); LinphoneCore *lc = linphone_chat_room_get_core(cr); LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(lc); if (linphone_im_notif_policy_get_send_imdn_delivered(policy) == TRUE) { - linphone_chat_message_send_imdn(cm, ImdnTypeDelivery); + linphone_chat_message_send_imdn(cm, ImdnTypeDelivery, reason); } } @@ -1165,7 +1194,7 @@ void linphone_chat_message_send_display_notification(LinphoneChatMessage *cm) { LinphoneCore *lc = linphone_chat_room_get_core(cr); LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(lc); if (linphone_im_notif_policy_get_send_imdn_displayed(policy) == TRUE) { - linphone_chat_message_send_imdn(cm, ImdnTypeDisplay); + linphone_chat_message_send_imdn(cm, ImdnTypeDisplay, LinphoneReasonNone); } } diff --git a/coreapi/error_info.c b/coreapi/error_info.c index 5ebab0a8f..102c68e10 100644 --- a/coreapi/error_info.c +++ b/coreapi/error_info.c @@ -69,50 +69,49 @@ const char *linphone_reason_to_string(LinphoneReason err){ return "unknown error"; } +typedef struct _error_code_reason_map { + int error_code; + LinphoneReason reason; +} error_code_reason_map_t; + +static const error_code_reason_map_t error_code_reason_map[] = { + { 200, LinphoneReasonNone }, + { 301, LinphoneReasonMovedPermanently }, + { 400, LinphoneReasonUnknown }, + { 401, LinphoneReasonUnauthorized }, + { 403, LinphoneReasonForbidden }, + { 404, LinphoneReasonNotFound }, + { 410, LinphoneReasonGone }, + { 415, LinphoneReasonUnsupportedContent }, + { 480, LinphoneReasonTemporarilyUnavailable }, + { 481, LinphoneReasonNoMatch }, + { 484, LinphoneReasonAddressIncomplete }, + { 486, LinphoneReasonBusy }, + { 488, LinphoneReasonNotAcceptable }, + { 501, LinphoneReasonNotImplemented }, + { 502, LinphoneReasonBadGateway }, + { 503, LinphoneReasonIOError }, + { 504, LinphoneReasonServerTimeout }, + { 600, LinphoneReasonDoNotDisturb }, + { 603, LinphoneReasonDeclined } +}; + LinphoneReason linphone_error_code_to_reason(int err) { - switch (err) { - case 200: - return LinphoneReasonNone; - case 301: - return LinphoneReasonMovedPermanently; - case 400: - return LinphoneReasonUnknown; - case 401: - return LinphoneReasonUnauthorized; - case 403: - return LinphoneReasonForbidden; - case 404: - return LinphoneReasonNotFound; - case 410: - return LinphoneReasonGone; - case 415: - return LinphoneReasonUnsupportedContent; - case 480: - return LinphoneReasonTemporarilyUnavailable; - case 481: - return LinphoneReasonNoMatch; - case 484: - return LinphoneReasonAddressIncomplete; - case 486: - return LinphoneReasonBusy; - case 488: - return LinphoneReasonNotAcceptable; - case 501: - return LinphoneReasonNotImplemented; - case 502: - return LinphoneReasonBadGateway; - case 503: - return LinphoneReasonIOError; - case 504: - return LinphoneReasonServerTimeout; - case 600: - return LinphoneReasonDoNotDisturb; - case 603: - return LinphoneReasonDeclined; + size_t i; + for (i = 0; i < (sizeof(error_code_reason_map) / sizeof(error_code_reason_map[0])); i++) { + if (error_code_reason_map[i].error_code == err) return error_code_reason_map[i].reason; } return LinphoneReasonUnknown; } +int linphone_reason_to_error_code(LinphoneReason reason) { + size_t i; + for (i = 0; i < (sizeof(error_code_reason_map) / sizeof(error_code_reason_map[0])); i++) { + if (error_code_reason_map[i].reason == reason) return error_code_reason_map[i].error_code; + } + return 400; +} + LinphoneReason linphone_error_info_get_reason(const LinphoneErrorInfo *ei) { const SalErrorInfo *sei = (const SalErrorInfo *)ei; diff --git a/coreapi/private.h b/coreapi/private.h index 76eaf0cea..02ad00503 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -614,7 +614,7 @@ void linphone_chat_room_add_weak_message(LinphoneChatRoom *cr, LinphoneChatMessa 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); -void linphone_chat_message_send_delivery_notification(LinphoneChatMessage *cm); +void linphone_chat_message_send_delivery_notification(LinphoneChatMessage *cm, LinphoneReason reason); void linphone_chat_message_send_display_notification(LinphoneChatMessage *cm); int linphone_chat_room_upload_file(LinphoneChatMessage *msg); void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg); diff --git a/include/linphone/error_info.h b/include/linphone/error_info.h index b898877fb..984d46279 100644 --- a/include/linphone/error_info.h +++ b/include/linphone/error_info.h @@ -90,12 +90,19 @@ extern "C" { LINPHONE_PUBLIC const char *linphone_reason_to_string(LinphoneReason err); /** - * Converts a error code to a LinphoneReason. + * Converts an error code to a LinphoneReason. * @param[in] err An error code * @return The LinphoneReason corresponding to the specified error code **/ LINPHONE_PUBLIC LinphoneReason linphone_error_code_to_reason(int err); +/** + * Converts a LinphoneReason to an error code. + * @param[in] reason A LinphoneReason + * @return The error code corresponding to the specified LinphoneReason + */ +LINPHONE_PUBLIC int linphone_reason_to_error_code(LinphoneReason reason); + /** * Get reason code from the error info. * @param[in] ei ErrorInfo object diff --git a/share/xml/Makefile.am b/share/xml/Makefile.am index c553a5c76..2af2b7d46 100644 --- a/share/xml/Makefile.am +++ b/share/xml/Makefile.am @@ -1 +1 @@ -EXTRA_DIST=lpconfig.xsd +EXTRA_DIST=lpconfig.xsd imdn.xsd diff --git a/share/xml/imdn.xsd b/share/xml/imdn.xsd new file mode 100644 index 000000000..9969b2b88 --- /dev/null +++ b/share/xml/imdn.xsd @@ -0,0 +1,16 @@ + + + + + + + + + + + + + diff --git a/tester/message_tester.c b/tester/message_tester.c index 00e109ec6..8f6f58a77 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -37,6 +37,9 @@ static char* message_external_body_url=NULL; +static const char *marie_zid_cache = "\nef7692d0792a67491ae2d44e005dbe0399643d953a2202dd9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000078000001cf011234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s72d80ab1cad243cf45634980c1d02cfb2df81ce0dd5dfcf1ebeacfc5345a917625d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b771930000000f00000000"; +static const char *pauline_zid_cache = "\n005dbe0399643d953a2202ddef7692d0792a67491ae2d44e9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000078000001cf011234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s81e6e6362c34dc974263d1f77cbb9a8d6d6a718330994379099a8fa19fb12faa25d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b771930000002e0000000001"; + void text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from_address, const char *msg) { stats* counters = get_stats(lc); counters->number_of_LinphoneMessageReceivedLegacy++; @@ -857,8 +860,8 @@ static void _is_composing_notification(bool_t lime_enabled) { /* set the zid caches files : create two ZID cache from this valid one inserting the auto-generated sip URI for the peer account as keys in ZID cache are indexed by peer sip uri */ ZIDCacheMarieFD = fopen_from_write_dir("tmpZIDCacheMarie.xml", "w"); ZIDCachePaulineFD = fopen_from_write_dir("tmpZIDCachePauline.xml", "w"); - fprintf(ZIDCacheMarieFD, "\nef7692d0792a67491ae2d44e005dbe0399643d953a2202dd9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000078000001cf011234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s72d80ab1cad243cf45634980c1d02cfb2df81ce0dd5dfcf1ebeacfc5345a917625d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b771930000000f00000000", linphone_address_as_string_uri_only(pauline->identity), linphone_address_as_string_uri_only(pauline->identity)); - fprintf(ZIDCachePaulineFD, "\n005dbe0399643d953a2202ddef7692d0792a67491ae2d44e9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000078000001cf011234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s81e6e6362c34dc974263d1f77cbb9a8d6d6a718330994379099a8fa19fb12faa25d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b771930000002e0000000001", linphone_address_as_string_uri_only(marie->identity), linphone_address_as_string_uri_only(marie->identity)); + fprintf(ZIDCacheMarieFD, marie_zid_cache, linphone_address_as_string_uri_only(pauline->identity), linphone_address_as_string_uri_only(pauline->identity)); + fprintf(ZIDCachePaulineFD, pauline_zid_cache, linphone_address_as_string_uri_only(marie->identity), linphone_address_as_string_uri_only(marie->identity)); fclose(ZIDCacheMarieFD); fclose(ZIDCachePaulineFD); @@ -1013,6 +1016,90 @@ static void im_notification_policy(void) { linphone_core_manager_destroy(pauline); } +static void _im_error_delivery_notification(bool_t online) { + FILE *ZIDCacheMarieFD, *ZIDCachePaulineFD; + LinphoneChatRoom *chat_room; + char *filepath; + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new( "pauline_tcp_rc"); + LinphoneChatMessage *msg; + LinphoneChatMessageCbs *cbs; + int dummy = 0; + + if (!linphone_core_lime_available(marie->lc)) { + ms_warning("Lime not available, skiping"); + goto end; + } + + /* Make sure lime is enabled */ + linphone_core_enable_lime(marie->lc, 1); + linphone_core_enable_lime(pauline->lc, 1); + + /* Set the zid cache files : create two ZID cache from this valid one inserting the auto-generated sip URI for the peer account as keys in ZID cache are indexed by peer sip uri. */ + ZIDCacheMarieFD = fopen_from_write_dir("tmpZIDCacheMarie.xml", "w"); + ZIDCachePaulineFD = fopen_from_write_dir("tmpZIDCachePauline.xml", "w"); + fprintf(ZIDCacheMarieFD, marie_zid_cache, linphone_address_as_string_uri_only(pauline->identity), linphone_address_as_string_uri_only(pauline->identity)); + fprintf(ZIDCachePaulineFD, pauline_zid_cache, linphone_address_as_string_uri_only(marie->identity), linphone_address_as_string_uri_only(marie->identity)); + fclose(ZIDCacheMarieFD); + fclose(ZIDCachePaulineFD); + + filepath = bc_tester_file("tmpZIDCacheMarie.xml"); + linphone_core_set_zrtp_secrets_file(marie->lc, filepath); + bc_free(filepath); + + filepath = bc_tester_file("tmpZIDCachePauline.xml"); + linphone_core_set_zrtp_secrets_file(pauline->lc, filepath); + bc_free(filepath); + + chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity); + + linphone_chat_room_send_message(chat_room, "Bla bla bla bla"); + BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1)); + BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceivedLegacy, 1)); + BC_ASSERT_PTR_NOT_NULL(marie->stat.last_received_chat_message); + if (marie->stat.last_received_chat_message) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marie->stat.last_received_chat_message), "Bla bla bla bla"); + } + + BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc, pauline->identity)); + + /* Clear the ZID cache of the receiver of the chat message and enable all IM notifications */ + linphone_core_set_zrtp_secrets_file(marie->lc, NULL); + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(marie->lc)); + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(pauline->lc)); + + msg = linphone_chat_room_create_message(chat_room, "Happy new year!"); + linphone_chat_message_ref(msg); + cbs = linphone_chat_message_get_callbacks(msg); + linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); + linphone_chat_room_send_chat_message(chat_room, msg); + if (!online) { + linphone_core_set_network_reachable(marie->lc, FALSE); + BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDelivered, 1, 60000)); + linphone_core_set_network_reachable(marie->lc, TRUE); + BC_ASSERT_TRUE (wait_for(marie->lc, marie->lc, &marie->stat.number_of_LinphoneRegistrationOk, 2)); + wait_for_until(pauline->lc, marie->lc, &dummy, 1, 1500); /* Just to sleep while iterating */ + } + 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)); + linphone_chat_message_unref(msg); + +end: + remove("tmpZIDCacheMarie.xml"); + remove("tmpZIDCachePauline.xml"); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +static void im_error_delivery_notification_online(void) { + _im_error_delivery_notification(TRUE); +} + +static void im_error_delivery_notification_offline(void) { + _im_error_delivery_notification(FALSE); +} + static void lime_text_message(void) { FILE *ZIDCacheMarieFD, *ZIDCachePaulineFD; LinphoneChatRoom* chat_room; @@ -1024,15 +1111,15 @@ static void lime_text_message(void) { ms_warning("Lime not available, skiping"); goto end; } - /* make sure lime is enabled and im notify policy is empty */ + /* make sure lime is enabled */ linphone_core_enable_lime(marie->lc, 1); linphone_core_enable_lime(pauline->lc, 1); /* set the zid caches files : create two ZID cache from this valid one inserting the auto-generated sip URI for the peer account as keys in ZID cache are indexed by peer sip uri */ ZIDCacheMarieFD = fopen_from_write_dir("tmpZIDCacheMarie.xml", "w"); ZIDCachePaulineFD = fopen_from_write_dir("tmpZIDCachePauline.xml", "w"); - fprintf(ZIDCacheMarieFD, "\nef7692d0792a67491ae2d44e005dbe0399643d953a2202dd9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000078000001cf011234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s72d80ab1cad243cf45634980c1d02cfb2df81ce0dd5dfcf1ebeacfc5345a917625d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b771930000000f00000000", linphone_address_as_string_uri_only(pauline->identity), linphone_address_as_string_uri_only(pauline->identity)); - fprintf(ZIDCachePaulineFD, "\n005dbe0399643d953a2202ddef7692d0792a67491ae2d44e9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000078000001cf011234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s81e6e6362c34dc974263d1f77cbb9a8d6d6a718330994379099a8fa19fb12faa25d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b771930000002e0000000001", linphone_address_as_string_uri_only(marie->identity), linphone_address_as_string_uri_only(marie->identity)); + fprintf(ZIDCacheMarieFD, marie_zid_cache, linphone_address_as_string_uri_only(pauline->identity), linphone_address_as_string_uri_only(pauline->identity)); + fprintf(ZIDCachePaulineFD, pauline_zid_cache, linphone_address_as_string_uri_only(marie->identity), linphone_address_as_string_uri_only(marie->identity)); fclose(ZIDCacheMarieFD); fclose(ZIDCachePaulineFD); @@ -1080,7 +1167,7 @@ static void lime_text_message_to_non_lime(void) { /* set the zid caches files : create two ZID cache from this valid one inserting the auto-generated sip URI for the peer account as keys in ZID cache are indexed by peer sip uri */ ZIDCachePaulineFD = fopen_from_write_dir("tmpZIDCachePauline.xml", "w"); - fprintf(ZIDCachePaulineFD, "\n005dbe0399643d953a2202ddef7692d0792a67491ae2d44e9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000078000001cf011234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s81e6e6362c34dc974263d1f77cbb9a8d6d6a718330994379099a8fa19fb12faa25d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b771930000002e0000000001", linphone_address_as_string_uri_only(marie->identity), linphone_address_as_string_uri_only(marie->identity)); + fprintf(ZIDCachePaulineFD, pauline_zid_cache, linphone_address_as_string_uri_only(marie->identity), linphone_address_as_string_uri_only(marie->identity)); fclose(ZIDCachePaulineFD); filepath = bc_tester_file("tmpZIDCachePauline.xml"); @@ -1135,7 +1222,7 @@ void lime_transfer_message_base(bool_t encrypt_file,bool_t download_file_from_st pauline_id = linphone_address_as_string_uri_only(pauline->identity); marie_id = linphone_address_as_string_uri_only(marie->identity); fprintf(ZIDCacheMarieFD, "\nef7692d0792a67491ae2d44e005dbe0399643d953a2202dd9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000078000001cf011234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778csal_set_uuid(lc->sal, account->instance_id);bdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s72d80ab1cad243cf45634980c1d02cfb2df81ce0dd5dfcf1ebeacfc5345a917625d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b771930000000f00000000", pauline_id, pauline_id); - fprintf(ZIDCachePaulineFD, "\n005dbe0399643d953a2202ddef7692d0792a67491ae2d44e9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000078000001cf011234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s81e6e6362c34dc974263d1f77cbb9a8d6d6a718330994379099a8fa19fb12faa25d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b771930000002e0000000001", marie_id, marie_id); + fprintf(ZIDCachePaulineFD, pauline_zid_cache, marie_id, marie_id); fclose(ZIDCacheMarieFD); fclose(ZIDCachePaulineFD); ms_free(marie_id); @@ -2181,6 +2268,8 @@ test_t message_tests[] = { TEST_ONE_TAG("IsComposing notification lime", is_composing_notification_with_lime, "LIME"), TEST_NO_TAG("IMDN notifications", imdn_notifications), TEST_NO_TAG("IM notification policy", im_notification_policy), + TEST_ONE_TAG("IM error delivery notification online", im_error_delivery_notification_online, "LIME"), + TEST_ONE_TAG("IM error delivery notification offline", im_error_delivery_notification_offline, "LIME"), TEST_ONE_TAG("Lime text message", lime_text_message, "LIME"), TEST_ONE_TAG("Lime text message to non lime", lime_text_message_to_non_lime, "LIME"), TEST_ONE_TAG("Lime transfer message", lime_transfer_message, "LIME"),