提交 833500ae authored 作者: Michael Jerris's avatar Michael Jerris

Fri Nov 21 04:52:55 CST 2008 Pekka Pessi <first.last@nokia.com>

  * nua: try to cope if a re-INVITE nor its ACK contain SDP
  
  Some SIP user-agents use INVITE without SDP offer to refresh session.
  By default, NUA sends an offer in 200 OK to such an INVITE and expects
  an answer back in ACK. Now nua tries to recover from such a Offer/Answer
  protocol error.
  
  Also, if NUTAG_REFRESH_WITHOUT_SDP(1) tag is used, and if the re-INVITE was
  received without SDP, no SDP offer is sent in 200 OK.
  
  Thanks for Anthony Minessale for reporting the problem.



git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@10829 d0543943-73ff-0310-b7d9-9358b9ac24b2
上级 bf201fc0
Tue Dec 16 14:46:55 CST 2008 Tue Dec 16 15:19:47 CST 2008
...@@ -1077,6 +1077,71 @@ START_TEST(call_2_3_2) ...@@ -1077,6 +1077,71 @@ START_TEST(call_2_3_2)
} }
END_TEST END_TEST
START_TEST(call_2_3_3)
{
nua_handle_t *nh;
struct message *response;
s2_case("2.3.3", "Handling re-INVITE without SDP gracefully",
"NUA receives INVITE, "
"re-INVITE without SDP (w/o NUTAG_REFRESH_WITHOUT_SDP(), "
"re-INVITE without SDP (using NUTAG_REFRESH_WITHOUT_SDP(), "
"sends BYE.");
nh = invite_to_nua(
TAG_END());
s2_request_to(dialog, SIP_METHOD_INVITE, NULL,
SIPTAG_USER_AGENT_STR("evil (evil) evil"),
TAG_END());
nua_respond(nh, SIP_200_OK, TAG_END());
fail_unless(s2_check_callstate(nua_callstate_completed));
response = s2_wait_for_response(200, SIP_METHOD_INVITE);
fail_if(!response);
s2_update_dialog(dialog, response);
fail_if(!response->sip->sip_content_type);
s2_free_message(response);
fail_if(s2_request_to(dialog, SIP_METHOD_ACK, NULL, TAG_END()));
fail_unless(s2_check_event(nua_i_ack, 200));
fail_unless(s2_check_callstate(nua_callstate_ready));
s2_fast_forward(10);
nua_set_hparams(nh, NUTAG_REFRESH_WITHOUT_SDP(1), TAG_END());
fail_unless(s2_check_event(nua_r_set_params, 200));
s2_request_to(dialog, SIP_METHOD_INVITE, NULL,
SIPTAG_USER_AGENT_STR("evil (evil) evil"),
TAG_END());
nua_respond(nh, SIP_200_OK, TAG_END());
fail_unless(s2_check_callstate(nua_callstate_completed));
response = s2_wait_for_response(200, SIP_METHOD_INVITE);
fail_if(!response);
s2_update_dialog(dialog, response);
fail_if(response->sip->sip_content_type);
s2_free_message(response);
fail_if(s2_request_to(dialog, SIP_METHOD_ACK, NULL, TAG_END()));
fail_unless(s2_check_event(nua_i_ack, 200));
fail_unless(s2_check_callstate(nua_callstate_ready));
bye_by_nua(nh, TAG_END());
nua_handle_destroy(nh);
}
END_TEST
TCase *session_timer_tcase(void) TCase *session_timer_tcase(void)
{ {
...@@ -1085,6 +1150,7 @@ TCase *session_timer_tcase(void) ...@@ -1085,6 +1150,7 @@ TCase *session_timer_tcase(void)
{ {
tcase_add_test(tc, call_2_3_1); tcase_add_test(tc, call_2_3_1);
tcase_add_test(tc, call_2_3_2); tcase_add_test(tc, call_2_3_2);
tcase_add_test(tc, call_2_3_3);
} }
return tc; return tc;
} }
......
...@@ -116,6 +116,7 @@ struct nua_server_request { ...@@ -116,6 +116,7 @@ struct nua_server_request {
unsigned sr_offer_sent:2; /**< We have offered SDP (reliably, if >1) */ unsigned sr_offer_sent:2; /**< We have offered SDP (reliably, if >1) */
unsigned sr_answer_recv:1; /**< We have received SDP answer */ unsigned sr_answer_recv:1; /**< We have received SDP answer */
unsigned :0; unsigned :0;
char const *sr_sdp; /**< SDP received from client */ char const *sr_sdp; /**< SDP received from client */
......
...@@ -301,6 +301,7 @@ int nua_stack_init_instance(nua_handle_t *nh, tagi_t const *tags) ...@@ -301,6 +301,7 @@ int nua_stack_init_instance(nua_handle_t *nh, tagi_t const *tags)
* NUTAG_PROXY() (aka NTATAG_DEFAULT_PROXY()) \n * NUTAG_PROXY() (aka NTATAG_DEFAULT_PROXY()) \n
* NUTAG_REFER_EXPIRES() \n * NUTAG_REFER_EXPIRES() \n
* NUTAG_REFER_WITH_ID() \n * NUTAG_REFER_WITH_ID() \n
* NUTAG_REFRESH_WITHOUT_SDP() \n
* NUTAG_REGISTRAR() \n * NUTAG_REGISTRAR() \n
* NUTAG_RETRY_COUNT() \n * NUTAG_RETRY_COUNT() \n
* NUTAG_SERVICE_ROUTE_ENABLE() \n * NUTAG_SERVICE_ROUTE_ENABLE() \n
...@@ -422,6 +423,7 @@ int nua_stack_init_instance(nua_handle_t *nh, tagi_t const *tags) ...@@ -422,6 +423,7 @@ int nua_stack_init_instance(nua_handle_t *nh, tagi_t const *tags)
* NUTAG_PROXY() (aka NTATAG_DEFAULT_PROXY()) \n * NUTAG_PROXY() (aka NTATAG_DEFAULT_PROXY()) \n
* NUTAG_REFER_EXPIRES() \n * NUTAG_REFER_EXPIRES() \n
* NUTAG_REFER_WITH_ID() \n * NUTAG_REFER_WITH_ID() \n
* NUTAG_REFRESH_WITHOUT_SDP() \n
* NUTAG_REGISTRAR() \n * NUTAG_REGISTRAR() \n
* NUTAG_RETRY_COUNT() \n * NUTAG_RETRY_COUNT() \n
* NUTAG_SERVICE_ROUTE_ENABLE() \n * NUTAG_SERVICE_ROUTE_ENABLE() \n
...@@ -770,6 +772,10 @@ static int nhp_set_tags(su_home_t *home, ...@@ -770,6 +772,10 @@ static int nhp_set_tags(su_home_t *home,
else if (tag == nutag_update_refresh) { else if (tag == nutag_update_refresh) {
NHP_SET(nhp, update_refresh, value != 0); NHP_SET(nhp, update_refresh, value != 0);
} }
/* NUTAG_REFRESH_WITHOUT_SDP(refresh_without_sdp) */
else if (tag == nutag_refresh_without_sdp) {
NHP_SET(nhp, refresh_without_sdp, value != 0);
}
/* NUTAG_ENABLEMESSAGE(message_enable) */ /* NUTAG_ENABLEMESSAGE(message_enable) */
else if (tag == nutag_enablemessage) { else if (tag == nutag_enablemessage) {
NHP_SET(nhp, message_enable, value != 0); NHP_SET(nhp, message_enable, value != 0);
...@@ -1478,6 +1484,7 @@ int nua_stack_set_smime_params(nua_t *nua, tagi_t const *tags) ...@@ -1478,6 +1484,7 @@ int nua_stack_set_smime_params(nua_t *nua, tagi_t const *tags)
* NUTAG_PATH_ENABLE() \n * NUTAG_PATH_ENABLE() \n
* NUTAG_REFER_EXPIRES() \n * NUTAG_REFER_EXPIRES() \n
* NUTAG_REFER_WITH_ID() \n * NUTAG_REFER_WITH_ID() \n
* NUTAG_REFRESH_WITHOUT_SDP() \n
* NUTAG_REGISTRAR() \n * NUTAG_REGISTRAR() \n
* NUTAG_RETRY_COUNT() \n * NUTAG_RETRY_COUNT() \n
* NUTAG_SERVICE_ROUTE_ENABLE() \n * NUTAG_SERVICE_ROUTE_ENABLE() \n
...@@ -1639,6 +1646,7 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, ...@@ -1639,6 +1646,7 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
TIF(NUTAG_MIN_SE, min_se), TIF(NUTAG_MIN_SE, min_se),
TIFD(NUTAG_SESSION_REFRESHER, refresher), TIFD(NUTAG_SESSION_REFRESHER, refresher),
TIF(NUTAG_UPDATE_REFRESH, update_refresh), TIF(NUTAG_UPDATE_REFRESH, update_refresh),
TIF(NUTAG_REFRESH_WITHOUT_SDP, refresh_without_sdp),
TIF(NUTAG_ENABLEMESSAGE, message_enable), TIF(NUTAG_ENABLEMESSAGE, message_enable),
TIF(NUTAG_ENABLEMESSENGER, win_messenger_enable), TIF(NUTAG_ENABLEMESSENGER, win_messenger_enable),
......
...@@ -82,6 +82,9 @@ struct nua_handle_preferences ...@@ -82,6 +82,9 @@ struct nua_handle_preferences
/** no (preference), local or remote */ /** no (preference), local or remote */
enum nua_session_refresher nhp_refresher; enum nua_session_refresher nhp_refresher;
unsigned nhp_update_refresh:1; /**< Use UPDATE to refresh */ unsigned nhp_update_refresh:1; /**< Use UPDATE to refresh */
/**< Accept refreshes without SDP */
unsigned nhp_refresh_without_sdp:1;
/* Messaging preferences */ /* Messaging preferences */
unsigned nhp_message_enable : 1; unsigned nhp_message_enable : 1;
...@@ -164,6 +167,7 @@ struct nua_handle_preferences ...@@ -164,6 +167,7 @@ struct nua_handle_preferences
unsigned nhb_min_se:1; unsigned nhb_min_se:1;
unsigned nhb_refresher:1; unsigned nhb_refresher:1;
unsigned nhb_update_refresh:1; unsigned nhb_update_refresh:1;
unsigned nhb_refresh_without_sdp:1;
unsigned nhb_message_enable:1; unsigned nhb_message_enable:1;
unsigned nhb_win_messenger_enable:1; unsigned nhb_win_messenger_enable:1;
unsigned nhb_message_auto_respond:1; unsigned nhb_message_auto_respond:1;
...@@ -179,9 +183,9 @@ struct nua_handle_preferences ...@@ -179,9 +183,9 @@ struct nua_handle_preferences
unsigned nhb_keepalive:1; unsigned nhb_keepalive:1;
unsigned nhb_keepalive_stream:1; unsigned nhb_keepalive_stream:1;
unsigned nhb_registrar:1; unsigned nhb_registrar:1;
unsigned :0; /* at most 32 bits before this point */
unsigned nhb_allow:1; unsigned nhb_allow:1;
unsigned :0; /* at most 32 bits before this point */
unsigned nhb_supported:1; unsigned nhb_supported:1;
unsigned nhb_allow_events:1; unsigned nhb_allow_events:1;
......
...@@ -182,7 +182,8 @@ ...@@ -182,7 +182,8 @@
* UPDATE requests. * UPDATE requests.
* Settings: * Settings:
* - NUTAG_MIN_SE(), NUTAG_SESSION_REFRESHER(), * - NUTAG_MIN_SE(), NUTAG_SESSION_REFRESHER(),
* NUTAG_SESSION_TIMER(), NUTAG_UPDATE_REFRESH() * NUTAG_SESSION_TIMER(), NUTAG_UPDATE_REFRESH(),
* NUTAG_REFRESH_WITHOUT_SDP(),
* - "timer" in NUTAG_SUPPORTED()/SIPTAG_SUPPORTED() * - "timer" in NUTAG_SUPPORTED()/SIPTAG_SUPPORTED()
* Specifications: * Specifications:
* - @RFC4028 * - @RFC4028
...@@ -954,6 +955,11 @@ tag_typedef_t nutag_invite_timer = UINTTAG_TYPEDEF(invite_timer); ...@@ -954,6 +955,11 @@ tag_typedef_t nutag_invite_timer = UINTTAG_TYPEDEF(invite_timer);
* @SessionExpires header sends a re-INVITE requests (or an UPDATE * @SessionExpires header sends a re-INVITE requests (or an UPDATE
* request if NUTAG_UPDATE_REFRESH(1) parameter tag has been set). * request if NUTAG_UPDATE_REFRESH(1) parameter tag has been set).
* *
* Some SIP user-agents use INVITE without SDP offer to refresh session.
* By default, NUA sends an offer in 200 OK to such an INVITE and expects
* an answer back in ACK. If NUTAG_REFRESH_WITHOUT_SDP(1) tag is used,
* no SDP offer is sent in 200 OK if re-INVITE was received without SDP.
*
* @par When to Use NUTAG_SESSION_TIMER()? * @par When to Use NUTAG_SESSION_TIMER()?
* *
* The session time extension is enabled ("timer" feature tag is included in * The session time extension is enabled ("timer" feature tag is included in
...@@ -1106,7 +1112,7 @@ tag_typedef_t nutag_session_refresher = INTTAG_TYPEDEF(session_refresher); ...@@ -1106,7 +1112,7 @@ tag_typedef_t nutag_session_refresher = INTTAG_TYPEDEF(session_refresher);
* Corresponding tag taking reference parameter is NUTAG_UPDATE_REFRESH_REF(). * Corresponding tag taking reference parameter is NUTAG_UPDATE_REFRESH_REF().
* *
* @sa #nua_r_update, NUTAG_SESSION_TIMER(), NUTAG_MIN_SE_REF(), * @sa #nua_r_update, NUTAG_SESSION_TIMER(), NUTAG_MIN_SE_REF(),
* NUTAG_UPDATE_REFRESH(), @RFC4028, @SessionExpires, @MinSE * NUTAG_SESSION_REFRESHER(), @RFC4028, @SessionExpires, @MinSE
*/ */
tag_typedef_t nutag_update_refresh = BOOLTAG_TYPEDEF(update_refresh); tag_typedef_t nutag_update_refresh = BOOLTAG_TYPEDEF(update_refresh);
...@@ -1115,6 +1121,45 @@ tag_typedef_t nutag_update_refresh = BOOLTAG_TYPEDEF(update_refresh); ...@@ -1115,6 +1121,45 @@ tag_typedef_t nutag_update_refresh = BOOLTAG_TYPEDEF(update_refresh);
*/ */
/**@def NUTAG_REFRESH_WITHOUT_SDP(x)
*
* Do not send offer in response if re-INVITE was received without SDP.
*
* Some SIP user-agents use INVITE without SDP offer to refresh session.
* By default, NUA sends an offer in 200 OK to such an INVITE and expects
* an answer back in ACK.
*
* If NUTAG_REFRESH_WITHOUT_SDP(1) tag is used, no SDP offer is sent in 200
* OK if re-INVITE was received without SDP.
*
* @par Used with
* nua_handle(), nua_invite(), nua_update(), nua_respond() \n
* nua_set_params() or nua_set_hparams() \n
* nua_get_params() or nua_get_hparams()
*
* See nua_set_hparams() for a complete list of all the nua operations that
* accept this tag.
*
* @par Parameter type
* int (boolean: nonzero is true, zero is false)
*
* @par Values
* - 1 (true, do not try to send offer in response to re-INVITE)
* - 0 (false, always use SDP offer-answer in re-INVITEs)
*
* Corresponding tag taking reference parameter is NUTAG_REFRESH_WITHOUT_SDP_REF().
*
* @sa #nua_r_update, NUTAG_SESSION_TIMER(), NUTAG_MIN_SE_REF(),
* NUTAG_SESSION_REFRESHER(), NUTAG_UPDATE_REFRESH(), @RFC4028,
* @SessionExpires, @MinSE
*/
tag_typedef_t nutag_refresh_without_sdp = BOOLTAG_TYPEDEF(refresh_without_sdp);
/**@def NUTAG_REFRESH_WITHOUT_SDP_REF(x)
* Reference tag for NUTAG_REFRESH_WITHOUT_SDP_REF().
*/
/**@def NUTAG_REFER_EXPIRES() /**@def NUTAG_REFER_EXPIRES()
* *
* Default lifetime for implicit subscriptions created by REFER. * Default lifetime for implicit subscriptions created by REFER.
......
...@@ -183,6 +183,12 @@ SOFIAPUBVAR tag_typedef_t nutag_update_refresh; ...@@ -183,6 +183,12 @@ SOFIAPUBVAR tag_typedef_t nutag_update_refresh;
#define NUTAG_UPDATE_REFRESH_REF(x) nutag_update_refresh_ref, tag_bool_vr((&(x))) #define NUTAG_UPDATE_REFRESH_REF(x) nutag_update_refresh_ref, tag_bool_vr((&(x)))
SOFIAPUBVAR tag_typedef_t nutag_update_refresh_ref; SOFIAPUBVAR tag_typedef_t nutag_update_refresh_ref;
#define NUTAG_REFRESH_WITHOUT_SDP(x) nutag_refresh_without_sdp, tag_bool_v((x))
SOFIAPUBVAR tag_typedef_t nutag_refresh_without_sdp;
#define NUTAG_REFRESH_WITHOUT_SDP_REF(x) \
nutag_refresh_without_sdp_ref, tag_bool_vr((&(x)))
SOFIAPUBVAR tag_typedef_t nutag_refresh_without_sdp_ref;
#define NUTAG_AUTOALERT(x) nutag_autoalert, tag_bool_v(x) #define NUTAG_AUTOALERT(x) nutag_autoalert, tag_bool_v(x)
SOFIAPUBVAR tag_typedef_t nutag_autoalert; SOFIAPUBVAR tag_typedef_t nutag_autoalert;
#define NUTAG_AUTOALERT_REF(x) nutag_autoalert_ref, tag_bool_vr(&(x)) #define NUTAG_AUTOALERT_REF(x) nutag_autoalert_ref, tag_bool_vr(&(x))
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论