Commit 5a6e5c36 authored by DanmeiChen's avatar DanmeiChen
Browse files

integrate retry-after for call decline

parent 346ac8f2
......@@ -39,6 +39,7 @@ static void error_info_clone(LinphoneErrorInfo *ei, const LinphoneErrorInfo *oth
ei->warnings = bctbx_strdup(other->warnings);
ei->full_string = bctbx_strdup(other->full_string);
ei->protocol_code = other->protocol_code;
ei->retry_after = other->retry_after;
}
BELLE_SIP_INSTANCIATE_VPTR(LinphoneErrorInfo, belle_sip_object_t,
......@@ -137,6 +138,23 @@ static const error_code_reason_map_t error_code_reason_map[] = {
{ 603, LinphoneReasonDeclined }
};
static const error_code_reason_map_t retry_after_code_reason_map[] = {
{ 404, LinphoneReasonNotFound },
{ 480, LinphoneReasonTemporarilyUnavailable },
{ 486, LinphoneReasonBusy },
{ 503, LinphoneReasonIOError },
{ 600, LinphoneReasonDoNotDisturb },
{ 603, LinphoneReasonDeclined }
};
bool_t linphone_error_code_is_retry_after(int err) {
size_t i;
for (i = 0; i < (sizeof(retry_after_code_reason_map) / sizeof(retry_after_code_reason_map[0])); i++) {
if (retry_after_code_reason_map[i].error_code == err) return true;
}
return false;
}
LinphoneReason linphone_error_code_to_reason(int err) {
size_t i;
for (i = 0; i < (sizeof(error_code_reason_map) / sizeof(error_code_reason_map[0])); i++) {
......@@ -160,6 +178,7 @@ static void linphone_error_info_reset(LinphoneErrorInfo *ei){
STRING_RESET(ei->full_string);
STRING_RESET(ei->warnings);
ei->protocol_code = 0;
ei->retry_after = 0;
if (ei->sub_ei) {
linphone_error_info_unref(ei->sub_ei);
ei->sub_ei = NULL;
......@@ -172,6 +191,7 @@ void linphone_error_info_from_sal(LinphoneErrorInfo *ei, const SalErrorInfo *sei
ei->full_string = bctbx_strdup(sei->full_string);
ei->warnings = bctbx_strdup(sei->warnings);
ei->protocol_code = sei->protocol_code;
ei->retry_after = sei->retry_after;
ei->protocol = bctbx_strdup(sei->protocol);
}
......@@ -220,6 +240,7 @@ void linphone_error_info_fields_to_sal(const LinphoneErrorInfo* ei, SalErrorInfo
sei->full_string = bctbx_strdup(ei->full_string);
sei->warnings = bctbx_strdup(ei->warnings);
sei->protocol_code = ei->protocol_code;
sei->retry_after = ei->retry_after;
sei->protocol = bctbx_strdup(ei->protocol);
}
......@@ -242,6 +263,9 @@ void linphone_error_info_set(LinphoneErrorInfo *ei, const char *protocol, Linpho
ei->warnings = bctbx_strdup(warning);
}
int linphone_error_info_get_retry_after(const LinphoneErrorInfo *ei){
return ei->retry_after;
}
LinphoneReason linphone_error_info_get_reason(const LinphoneErrorInfo *ei) {
return ei->reason;
......@@ -272,6 +296,10 @@ LinphoneErrorInfo * linphone_error_info_get_sub_error_info(const LinphoneErrorIn
return ei->sub_ei;
}
void linphone_error_info_set_retry_after(LinphoneErrorInfo *ei, int retry_after){
ei->retry_after = retry_after;
}
void linphone_error_info_set_reason(LinphoneErrorInfo *ei, LinphoneReason reason){
ei->reason = reason;
}
......
......@@ -717,6 +717,7 @@ struct _LinphoneErrorInfo{
char *phrase; /*from SIP response*/
char *warnings; /*from SIP response*/
char *full_string; /*concatenation of status_string + warnings*/
int retry_after;
struct _LinphoneErrorInfo *sub_ei;
};
......
......@@ -55,6 +55,13 @@ LINPHONE_PUBLIC LinphoneErrorInfo *linphone_error_info_ref(LinphoneErrorInfo *ei
**/
LINPHONE_PUBLIC void linphone_error_info_unref(LinphoneErrorInfo *ei);
/**
* Get Retry-After delay second from the error info.
* @param[in] ei ErrorInfo object
* @return The Retry-After delay second
**/
LINPHONE_PUBLIC int linphone_error_info_get_retry_after(const LinphoneErrorInfo *ei);
/**
* Get reason code from the error info.
* @param[in] ei ErrorInfo object
......@@ -121,6 +128,13 @@ LINPHONE_PUBLIC void linphone_error_info_set(LinphoneErrorInfo *ei, const char *
*/
LINPHONE_PUBLIC void linphone_error_info_set_sub_error_info(LinphoneErrorInfo *ei, LinphoneErrorInfo *appended_ei);
/**
* Assign retry-after value to a #LinphoneErrorInfo object.
* @param[in] ei ErrorInfo object
* @param[in] retry_after the retry-after value
*/
LINPHONE_PUBLIC void linphone_error_info_set_retry_after(LinphoneErrorInfo *ei, int retry_after);
/**
* Assign reason #LinphoneReason to a #LinphoneErrorInfo object.
* @param[in] ei ErrorInfo object
......
......@@ -151,6 +151,14 @@ LINPHONE_PUBLIC const char* linphone_transport_to_string(LinphoneTransportType t
**/
LINPHONE_PUBLIC LinphoneTransportType linphone_transport_parse(const char* transport);
/**
* Check whether an error code is in Retry-After field.
* @param[in] err An error code
* @return TRUE if it is in Retry-After field
* @ingroup misc
**/
LINPHONE_PUBLIC bool_t linphone_error_code_is_retry_after(int err);
/**
* Converts an error code to a LinphoneReason.
* @param[in] err An error code
......
......@@ -400,6 +400,7 @@ typedef struct SalErrorInfo{
char *warnings;
char *protocol;
char *full_string; /*concatenation of status_string + warnings*/
int retry_after;
struct SalErrorInfo *sub_sei;
}SalErrorInfo;
......
......@@ -1039,6 +1039,7 @@ belle_sip_header_reason_t *SalCallOp::makeReasonHeader (const SalErrorInfo *info
int SalCallOp::declineWithErrorInfo (const SalErrorInfo *info, const SalAddress *redirectionAddr) {
belle_sip_header_contact_t *contactHeader = nullptr;
belle_sip_header_retry_after_t *retryAfterHeader = nullptr;
int status = info->protocol_code;
if (info->reason == SalReasonRedirect) {
......@@ -1058,11 +1059,17 @@ int SalCallOp::declineWithErrorInfo (const SalErrorInfo *info, const SalAddress
}
auto response = createResponseFromRequest(belle_sip_transaction_get_request(transaction), status);
auto reasonHeader = makeReasonHeader(info->sub_sei);
if (info->retry_after > 0)
retryAfterHeader = belle_sip_header_retry_after_create(info->retry_after);
if (reasonHeader)
belle_sip_message_add_header(BELLE_SIP_MESSAGE(response), BELLE_SIP_HEADER(reasonHeader));
if (contactHeader)
belle_sip_message_add_header(BELLE_SIP_MESSAGE(response), BELLE_SIP_HEADER(contactHeader));
if (retryAfterHeader)
belle_sip_message_add_header(BELLE_SIP_MESSAGE(response), BELLE_SIP_HEADER(retryAfterHeader));
belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(transaction), response);
return 0;
}
......
......@@ -1108,6 +1108,67 @@ static void call_declined_with_error(void) {
linphone_core_manager_destroy(caller_mgr);
}
static void call_declined_with_retry_after(void) {
LinphoneCoreManager* callee_mgr = linphone_core_manager_new("marie_rc");
LinphoneCoreManager* caller_mgr = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
LinphoneCall* in_call = NULL;
LinphoneCall* out_call = linphone_core_invite_address(caller_mgr->lc,callee_mgr->identity);
LinphoneFactory* factory = linphone_factory_get();
const LinphoneErrorInfo* rcvd_ei;
const LinphoneErrorInfo* sub_rcvd_ei;
LinphoneErrorInfo *ei = linphone_factory_create_error_info(factory);
LinphoneErrorInfo *reason_ei = linphone_factory_create_error_info(factory);
linphone_error_info_set(ei, "SIP", LinphoneReasonDeclined, 603, "Decline", NULL); //ordre des arguments à vérifier
linphone_error_info_set(reason_ei, "hardware", LinphoneReasonDeclined, 66, "J'ai plus de batterie", NULL);
BC_ASSERT_TRUE(linphone_error_code_is_retry_after(linphone_error_info_get_protocol_code(ei)));
linphone_error_info_set_retry_after(ei, 120);
linphone_error_info_set_sub_error_info(ei, reason_ei);
BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallIncomingReceived,1));
BC_ASSERT_PTR_NOT_NULL(in_call=linphone_core_get_current_call(callee_mgr->lc));
linphone_call_ref(out_call);
BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallOutgoingRinging,1));
BC_ASSERT_PTR_NOT_NULL(in_call=linphone_core_get_current_call(callee_mgr->lc));
if (in_call) {
linphone_call_ref(in_call);
linphone_call_decline_with_error_info(in_call, ei);
BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallEnd,1));
BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallEnd,1));
rcvd_ei = linphone_call_get_error_info(out_call);
sub_rcvd_ei = linphone_error_info_get_sub_error_info(rcvd_ei);
BC_ASSERT_STRING_EQUAL(linphone_error_info_get_phrase(rcvd_ei), "Decline");
BC_ASSERT_STRING_EQUAL(linphone_error_info_get_protocol(rcvd_ei), "SIP");
BC_ASSERT_STRING_EQUAL(linphone_error_info_get_phrase(sub_rcvd_ei), "J'ai plus de batterie");
BC_ASSERT_STRING_EQUAL(linphone_error_info_get_protocol(sub_rcvd_ei), "hardware");
BC_ASSERT_GREATER(linphone_error_info_get_retry_after(rcvd_ei), 0, int, "%d");
BC_ASSERT_EQUAL(linphone_call_get_reason(in_call),LinphoneReasonDeclined, int, "%d");
BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(in_call)),LinphoneCallDeclined, int, "%d");
BC_ASSERT_EQUAL(linphone_call_get_reason(out_call),LinphoneReasonDeclined, int, "%d");
BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(out_call)),LinphoneCallDeclined, int, "%d");
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->lc,&caller_mgr->stat.number_of_LinphoneCallReleased,1));
linphone_call_unref(in_call);
}
linphone_call_unref(out_call);
linphone_error_info_unref(reason_ei);
linphone_error_info_unref(ei);
linphone_core_manager_destroy(callee_mgr);
linphone_core_manager_destroy(caller_mgr);
}
static void call_declined_base(bool_t use_timeout) {
LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
......@@ -5141,6 +5202,7 @@ test_t call_tests[] = {
TEST_NO_TAG("Call declined", call_declined),
TEST_NO_TAG("Call declined on timeout",call_declined_on_timeout),
TEST_NO_TAG("Call declined with error", call_declined_with_error),
TEST_NO_TAG("Call declined with retry after", call_declined_with_retry_after),
TEST_NO_TAG("Cancelled call", cancelled_call),
TEST_NO_TAG("Early cancelled call", early_cancelled_call),
TEST_NO_TAG("Call with DNS timeout", call_with_dns_time_out),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment