mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-18 01:28:42 +00:00
Fri Jan 23 11:13:41 CST 2009 Pekka Pessi <first.last@nokia.com>
* sresolv: caching SRES_RECORD_ERR in case a CNAME is returned, too Tracing the CNAMEs when doing cache lookups. git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@11844 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
ba7a77e7da
commit
b7bc5240f0
@ -1 +1 @@
|
|||||||
Wed Feb 11 11:08:29 CST 2009
|
Wed Feb 11 11:12:10 CST 2009
|
||||||
|
522
libs/sofia-sip/libsofia-sip-ua/nua/check_simple.c
Normal file
522
libs/sofia-sip/libsofia-sip-ua/nua/check_simple.c
Normal file
@ -0,0 +1,522 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Sofia-SIP package
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Nokia Corporation.
|
||||||
|
*
|
||||||
|
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**@CFILE check_events.c
|
||||||
|
*
|
||||||
|
* @brief NUA module tests for SIP events
|
||||||
|
*
|
||||||
|
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||||
|
*
|
||||||
|
* @copyright (C) 2008 Nokia Corporation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "check_nua.h"
|
||||||
|
|
||||||
|
#include "test_s2.h"
|
||||||
|
|
||||||
|
#include <sofia-sip/sip_status.h>
|
||||||
|
#include <sofia-sip/sip_header.h>
|
||||||
|
#include <sofia-sip/soa.h>
|
||||||
|
#include <sofia-sip/su_tagarg.h>
|
||||||
|
#include <sofia-sip/su_string.h>
|
||||||
|
#include <sofia-sip/su_tag_io.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
/* define XXX as 1 in order to see all failing test cases */
|
||||||
|
#ifndef XXX
|
||||||
|
#define XXX (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ====================================================================== */
|
||||||
|
|
||||||
|
static nua_t *nua;
|
||||||
|
static soa_session_t *soa = NULL;
|
||||||
|
static struct dialog *dialog = NULL;
|
||||||
|
|
||||||
|
#define CRLF "\r\n"
|
||||||
|
|
||||||
|
void s2_dialog_setup(void)
|
||||||
|
{
|
||||||
|
nua = s2_nua_setup("simple",
|
||||||
|
SIPTAG_ORGANIZATION_STR("Pussy Galore's Flying Circus"),
|
||||||
|
NUTAG_OUTBOUND("no-options-keepalive, no-validate"),
|
||||||
|
TAG_END());
|
||||||
|
|
||||||
|
soa = soa_create(NULL, s2->root, NULL);
|
||||||
|
|
||||||
|
fail_if(!soa);
|
||||||
|
|
||||||
|
soa_set_params(soa,
|
||||||
|
SOATAG_USER_SDP_STR("m=audio 5008 RTP/AVP 8 0" CRLF
|
||||||
|
"m=video 5010 RTP/AVP 34" CRLF),
|
||||||
|
TAG_END());
|
||||||
|
|
||||||
|
dialog = su_home_new(sizeof *dialog); fail_if(!dialog);
|
||||||
|
|
||||||
|
s2_register_setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void s2_dialog_teardown(void)
|
||||||
|
{
|
||||||
|
s2_teardown_started("simple");
|
||||||
|
|
||||||
|
s2_register_teardown();
|
||||||
|
|
||||||
|
nua_shutdown(nua);
|
||||||
|
|
||||||
|
fail_unless(s2_check_event(nua_r_shutdown, 200));
|
||||||
|
|
||||||
|
s2_nua_teardown();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char const presence_open[] =
|
||||||
|
"<?xml version='1.0' encoding='UTF-8'?>\n"
|
||||||
|
"<presence xmlns='urn:ietf:params:xml:ns:cpim-pidf' \n"
|
||||||
|
" entity='pres:bob@example.org'>\n"
|
||||||
|
" <tuple id='ksac9udshce'>\n"
|
||||||
|
" <status><basic>open</basic></status>\n"
|
||||||
|
" <contact priority='1.0'>sip:bob@example.org</contact>\n"
|
||||||
|
" </tuple>\n"
|
||||||
|
"</presence>\n";
|
||||||
|
|
||||||
|
static char const presence_closed[] =
|
||||||
|
"<?xml version='1.0' encoding='UTF-8'?>\n"
|
||||||
|
"<presence xmlns='urn:ietf:params:xml:ns:cpim-pidf' \n"
|
||||||
|
" entity='pres:bob@example.org'>\n"
|
||||||
|
" <tuple id='ksac9udshce'>\n"
|
||||||
|
" <status><basic>closed</basic></status>\n"
|
||||||
|
" </tuple>\n"
|
||||||
|
"</presence>\n";
|
||||||
|
|
||||||
|
static char const *event_type = "presence";
|
||||||
|
static char const *event_mime_type = "application/pidf+xml";
|
||||||
|
static char const *event_state = presence_open;
|
||||||
|
static char const *subscription_state = "active;expires=600";
|
||||||
|
|
||||||
|
static struct event *
|
||||||
|
respond_to_subscribe(struct message *subscribe,
|
||||||
|
nua_event_t expect_event,
|
||||||
|
enum nua_substate expect_substate,
|
||||||
|
int status, char const *phrase,
|
||||||
|
tag_type_t tag, tag_value_t value, ...)
|
||||||
|
{
|
||||||
|
struct event *event;
|
||||||
|
ta_list ta;
|
||||||
|
|
||||||
|
ta_start(ta, tag, value);
|
||||||
|
s2_respond_to(subscribe, dialog, status, phrase,
|
||||||
|
ta_tags(ta));
|
||||||
|
ta_end(ta);
|
||||||
|
|
||||||
|
event = s2_wait_for_event(expect_event, status); fail_if(!event);
|
||||||
|
fail_unless(s2_check_substate(event, expect_substate));
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct event *
|
||||||
|
notify_to_nua(enum nua_substate expect_substate,
|
||||||
|
tag_type_t tag, tag_value_t value, ...)
|
||||||
|
{
|
||||||
|
struct event *event;
|
||||||
|
struct message *response;
|
||||||
|
ta_list ta;
|
||||||
|
|
||||||
|
ta_start(ta, tag, value);
|
||||||
|
fail_if(s2_request_to(dialog, SIP_METHOD_NOTIFY, NULL,
|
||||||
|
SIPTAG_CONTENT_TYPE_STR(event_mime_type),
|
||||||
|
SIPTAG_PAYLOAD_STR(event_state),
|
||||||
|
ta_tags(ta)));
|
||||||
|
ta_end(ta);
|
||||||
|
|
||||||
|
response = s2_wait_for_response(200, SIP_METHOD_NOTIFY);
|
||||||
|
fail_if(!response);
|
||||||
|
s2_free_message(response);
|
||||||
|
|
||||||
|
event = s2_wait_for_event(nua_i_notify, 200); fail_if(!event);
|
||||||
|
fail_unless(s2_check_substate(event, expect_substate));
|
||||||
|
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int send_notify_before_response = 0;
|
||||||
|
|
||||||
|
static struct event *
|
||||||
|
subscription_by_nua(nua_handle_t *nh,
|
||||||
|
enum nua_substate current,
|
||||||
|
tag_type_t tag, tag_value_t value, ...)
|
||||||
|
{
|
||||||
|
struct message *subscribe;
|
||||||
|
struct event *notify, *event;
|
||||||
|
ta_list ta;
|
||||||
|
enum nua_substate substate = nua_substate_active;
|
||||||
|
char const *substate_str = subscription_state;
|
||||||
|
char const *expires = "600";
|
||||||
|
|
||||||
|
subscribe = s2_wait_for_request(SIP_METHOD_SUBSCRIBE);
|
||||||
|
if (event_type)
|
||||||
|
fail_if(!subscribe->sip->sip_event ||
|
||||||
|
strcmp(event_type, subscribe->sip->sip_event->o_type));
|
||||||
|
|
||||||
|
if (subscribe->sip->sip_expires && subscribe->sip->sip_expires->ex_delta == 0) {
|
||||||
|
substate = nua_substate_terminated;
|
||||||
|
substate_str = "terminated;reason=timeout";
|
||||||
|
expires = "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
ta_start(ta, tag, value);
|
||||||
|
|
||||||
|
if (send_notify_before_response) {
|
||||||
|
s2_save_uas_dialog(dialog, subscribe->sip);
|
||||||
|
notify = notify_to_nua(substate,
|
||||||
|
SIPTAG_EVENT(subscribe->sip->sip_event),
|
||||||
|
SIPTAG_SUBSCRIPTION_STATE_STR(substate_str),
|
||||||
|
ta_tags(ta));
|
||||||
|
event = respond_to_subscribe(subscribe, nua_r_subscribe, substate,
|
||||||
|
SIP_200_OK,
|
||||||
|
SIPTAG_EXPIRES_STR(expires),
|
||||||
|
TAG_END());
|
||||||
|
s2_free_event(event);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
event = respond_to_subscribe(subscribe, nua_r_subscribe, current,
|
||||||
|
SIP_202_ACCEPTED,
|
||||||
|
SIPTAG_EXPIRES_STR(expires),
|
||||||
|
TAG_END());
|
||||||
|
s2_free_event(event);
|
||||||
|
notify = notify_to_nua(substate,
|
||||||
|
SIPTAG_EVENT(subscribe->sip->sip_event),
|
||||||
|
SIPTAG_SUBSCRIPTION_STATE_STR(substate_str),
|
||||||
|
ta_tags(ta));
|
||||||
|
}
|
||||||
|
|
||||||
|
s2_free_message(subscribe);
|
||||||
|
|
||||||
|
return notify;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
unsubscribe_by_nua(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
|
||||||
|
{
|
||||||
|
struct message *subscribe, *response;
|
||||||
|
struct event *event;
|
||||||
|
|
||||||
|
nua_unsubscribe(nh, TAG_END());
|
||||||
|
subscribe = s2_wait_for_request(SIP_METHOD_SUBSCRIBE);
|
||||||
|
|
||||||
|
s2_respond_to(subscribe, dialog, SIP_200_OK, SIPTAG_EXPIRES_STR("0"), TAG_END());
|
||||||
|
|
||||||
|
event = s2_wait_for_event(nua_r_unsubscribe, 200); fail_if(!event);
|
||||||
|
fail_unless(s2_check_substate(event, nua_substate_active));
|
||||||
|
s2_free_event(event);
|
||||||
|
|
||||||
|
fail_if(s2_request_to(dialog, SIP_METHOD_NOTIFY, NULL,
|
||||||
|
SIPTAG_EVENT(subscribe->sip->sip_event),
|
||||||
|
SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=tiemout"),
|
||||||
|
SIPTAG_CONTENT_TYPE_STR(event_mime_type),
|
||||||
|
SIPTAG_PAYLOAD_STR(event_state),
|
||||||
|
TAG_END()));
|
||||||
|
|
||||||
|
event = s2_wait_for_event(nua_i_notify, 200); fail_if(!event);
|
||||||
|
fail_unless(s2_check_substate(event, nua_substate_terminated));
|
||||||
|
s2_free_event(event);
|
||||||
|
|
||||||
|
response = s2_wait_for_response(200, SIP_METHOD_NOTIFY);
|
||||||
|
fail_if(!response);
|
||||||
|
s2_free_message(response); s2_free_message(subscribe);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ====================================================================== */
|
||||||
|
/* 6 - Subscribe/notify */
|
||||||
|
|
||||||
|
START_TEST(subscribe_6_1_1)
|
||||||
|
{
|
||||||
|
nua_handle_t *nh;
|
||||||
|
struct event *notify;
|
||||||
|
s2_case("6.1.1", "Basic subscription",
|
||||||
|
"NUA sends SUBSCRIBE, waits for NOTIFY, sends un-SUBSCRIBE");
|
||||||
|
|
||||||
|
nh = nua_handle(nua, NULL, SIPTAG_TO(s2->local), TAG_END());
|
||||||
|
nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), TAG_END());
|
||||||
|
notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END());
|
||||||
|
s2_free_event(notify);
|
||||||
|
unsubscribe_by_nua(nh, TAG_END());
|
||||||
|
nua_handle_destroy(nh);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(subscribe_6_1_2)
|
||||||
|
{
|
||||||
|
nua_handle_t *nh;
|
||||||
|
struct message *subscribe, *response;
|
||||||
|
struct event *notify, *event;
|
||||||
|
|
||||||
|
s2_case("6.1.2", "Basic subscription with refresh",
|
||||||
|
"NUA sends SUBSCRIBE, waits for NOTIFY, "
|
||||||
|
"sends re-SUBSCRIBE, waits for NOTIFY, "
|
||||||
|
"sends un-SUBSCRIBE");
|
||||||
|
|
||||||
|
send_notify_before_response = 1;
|
||||||
|
|
||||||
|
nh = nua_handle(nua, NULL, SIPTAG_TO(s2->local), TAG_END());
|
||||||
|
nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), TAG_END());
|
||||||
|
notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END());
|
||||||
|
s2_free_event(notify);
|
||||||
|
|
||||||
|
/* Wait for refresh */
|
||||||
|
s2_fast_forward(600);
|
||||||
|
subscribe = s2_wait_for_request(SIP_METHOD_SUBSCRIBE);
|
||||||
|
s2_respond_to(subscribe, dialog, SIP_200_OK,
|
||||||
|
SIPTAG_EXPIRES_STR("600"),
|
||||||
|
TAG_END());
|
||||||
|
|
||||||
|
event = s2_wait_for_event(nua_r_subscribe, 200); fail_if(!event);
|
||||||
|
fail_unless(s2_check_substate(event, nua_substate_active));
|
||||||
|
s2_free_event(event);
|
||||||
|
|
||||||
|
fail_if(s2_request_to(dialog, SIP_METHOD_NOTIFY, NULL,
|
||||||
|
SIPTAG_EVENT(subscribe->sip->sip_event),
|
||||||
|
SIPTAG_SUBSCRIPTION_STATE_STR("active;expires=600"),
|
||||||
|
SIPTAG_CONTENT_TYPE_STR(event_mime_type),
|
||||||
|
SIPTAG_PAYLOAD_STR(event_state),
|
||||||
|
TAG_END()));
|
||||||
|
event = s2_wait_for_event(nua_i_notify, 200); fail_if(!event);
|
||||||
|
fail_unless(s2_check_substate(event, nua_substate_active));
|
||||||
|
s2_free_event(event);
|
||||||
|
response = s2_wait_for_response(200, SIP_METHOD_NOTIFY);
|
||||||
|
fail_if(!response);
|
||||||
|
s2_free_message(response);
|
||||||
|
|
||||||
|
unsubscribe_by_nua(nh, TAG_END());
|
||||||
|
|
||||||
|
nua_handle_destroy(nh);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(subscribe_6_1_3)
|
||||||
|
{
|
||||||
|
nua_handle_t *nh;
|
||||||
|
struct message *response;
|
||||||
|
struct event *notify, *event;
|
||||||
|
|
||||||
|
s2_case("6.1.3", "Subscription terminated by notifier",
|
||||||
|
"NUA sends SUBSCRIBE, waits for NOTIFY, "
|
||||||
|
"gets NOTIFY terminating the subscription,");
|
||||||
|
|
||||||
|
nh = nua_handle(nua, NULL, SIPTAG_TO(s2->local), TAG_END());
|
||||||
|
nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), TAG_END());
|
||||||
|
notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END());
|
||||||
|
s2_free_event(notify);
|
||||||
|
|
||||||
|
fail_if(s2_request_to(dialog, SIP_METHOD_NOTIFY, NULL,
|
||||||
|
SIPTAG_EVENT_STR(event_type),
|
||||||
|
SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"),
|
||||||
|
TAG_END()));
|
||||||
|
event = s2_wait_for_event(nua_i_notify, 200); fail_if(!event);
|
||||||
|
fail_unless(s2_check_substate(event, nua_substate_terminated));
|
||||||
|
s2_free_event(event);
|
||||||
|
response = s2_wait_for_response(200, SIP_METHOD_NOTIFY);
|
||||||
|
fail_if(!response);
|
||||||
|
s2_free_message(response);
|
||||||
|
|
||||||
|
nua_handle_destroy(nh);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(subscribe_6_1_4)
|
||||||
|
{
|
||||||
|
nua_handle_t *nh;
|
||||||
|
struct message *response;
|
||||||
|
struct event *notify, *event;
|
||||||
|
|
||||||
|
s2_case("6.1.4", "Subscription terminated by notifier, re-established",
|
||||||
|
"NUA sends SUBSCRIBE, waits for NOTIFY, "
|
||||||
|
"gets NOTIFY terminating the subscription,");
|
||||||
|
|
||||||
|
nh = nua_handle(nua, NULL, SIPTAG_TO(s2->local), TAG_END());
|
||||||
|
nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), TAG_END());
|
||||||
|
notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END());
|
||||||
|
s2_free_event(notify);
|
||||||
|
|
||||||
|
fail_if(s2_request_to(dialog, SIP_METHOD_NOTIFY, NULL,
|
||||||
|
SIPTAG_EVENT_STR(event_type),
|
||||||
|
SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=deactivated"),
|
||||||
|
TAG_END()));
|
||||||
|
event = s2_wait_for_event(nua_i_notify, 200); fail_if(!event);
|
||||||
|
fail_unless(s2_check_substate(event, nua_substate_embryonic));
|
||||||
|
s2_free_event(event);
|
||||||
|
response = s2_wait_for_response(200, SIP_METHOD_NOTIFY);
|
||||||
|
fail_if(!response);
|
||||||
|
s2_free_message(response);
|
||||||
|
|
||||||
|
su_home_unref((void *)dialog), dialog = su_home_new(sizeof *dialog); fail_if(!dialog);
|
||||||
|
|
||||||
|
s2_fast_forward(5);
|
||||||
|
/* nua re-establishes the subscription */
|
||||||
|
notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END());
|
||||||
|
s2_free_event(notify);
|
||||||
|
|
||||||
|
/* Unsubscribe with nua_subscribe() Expires: 0 */
|
||||||
|
nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), SIPTAG_EXPIRES_STR("0"), TAG_END());
|
||||||
|
notify = subscription_by_nua(nh, nua_substate_active, TAG_END());
|
||||||
|
s2_free_event(notify);
|
||||||
|
|
||||||
|
nua_handle_destroy(nh);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
TCase *subscribe_tcase(void)
|
||||||
|
{
|
||||||
|
TCase *tc = tcase_create("6.1 - Basic SUBSCRIBE_");
|
||||||
|
tcase_add_checked_fixture(tc, s2_dialog_setup, s2_dialog_teardown);
|
||||||
|
{
|
||||||
|
tcase_add_test(tc, subscribe_6_1_1);
|
||||||
|
tcase_add_test(tc, subscribe_6_1_2);
|
||||||
|
tcase_add_test(tc, subscribe_6_1_3);
|
||||||
|
tcase_add_test(tc, subscribe_6_1_4);
|
||||||
|
}
|
||||||
|
return tc;
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(fetch_6_2_1)
|
||||||
|
{
|
||||||
|
nua_handle_t *nh;
|
||||||
|
struct event *notify;
|
||||||
|
|
||||||
|
s2_case("6.2.1", "Event fetch - NOTIFY after 202",
|
||||||
|
"NUA sends SUBSCRIBE with Expires 0, waits for NOTIFY");
|
||||||
|
|
||||||
|
nh = nua_handle(nua, NULL, SIPTAG_TO(s2->local), TAG_END());
|
||||||
|
nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), SIPTAG_EXPIRES_STR("0"), TAG_END());
|
||||||
|
notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END());
|
||||||
|
s2_check_substate(notify, nua_substate_terminated);
|
||||||
|
s2_free_event(notify);
|
||||||
|
nua_handle_destroy(nh);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(fetch_6_2_2)
|
||||||
|
{
|
||||||
|
nua_handle_t *nh;
|
||||||
|
struct event *notify;
|
||||||
|
|
||||||
|
s2_case("6.2.2", "Event fetch - NOTIFY before 200",
|
||||||
|
"NUA sends SUBSCRIBE with Expires 0, waits for NOTIFY");
|
||||||
|
|
||||||
|
send_notify_before_response = 1;
|
||||||
|
|
||||||
|
nh = nua_handle(nua, NULL, SIPTAG_TO(s2->local), TAG_END());
|
||||||
|
nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), SIPTAG_EXPIRES_STR("0"), TAG_END());
|
||||||
|
notify = subscription_by_nua(nh, nua_substate_embryonic, TAG_END());
|
||||||
|
s2_check_substate(notify, nua_substate_terminated);
|
||||||
|
s2_free_event(notify);
|
||||||
|
nua_handle_destroy(nh);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(fetch_6_2_3)
|
||||||
|
{
|
||||||
|
nua_handle_t *nh;
|
||||||
|
struct message *subscribe;
|
||||||
|
struct event *event;
|
||||||
|
|
||||||
|
s2_case("6.2.3", "Event fetch - no NOTIFY",
|
||||||
|
"NUA sends SUBSCRIBE with Expires 0, waits for NOTIFY, times out");
|
||||||
|
|
||||||
|
nh = nua_handle(nua, NULL, SIPTAG_TO(s2->local), TAG_END());
|
||||||
|
nua_subscribe(nh, SIPTAG_EVENT_STR(event_type), SIPTAG_EXPIRES_STR("0"), TAG_END());
|
||||||
|
subscribe = s2_wait_for_request(SIP_METHOD_SUBSCRIBE);
|
||||||
|
s2_respond_to(subscribe, dialog, SIP_202_ACCEPTED,
|
||||||
|
SIPTAG_EXPIRES_STR("0"), TAG_END());
|
||||||
|
s2_free_message(subscribe);
|
||||||
|
|
||||||
|
event = s2_wait_for_event(nua_r_subscribe, 202); fail_if(!event);
|
||||||
|
fail_unless(s2_check_substate(event, nua_substate_embryonic));
|
||||||
|
s2_free_event(event);
|
||||||
|
|
||||||
|
s2_fast_forward(600);
|
||||||
|
|
||||||
|
event = s2_wait_for_event(nua_i_notify, 408); fail_if(!event);
|
||||||
|
fail_unless(s2_check_substate(event, nua_substate_terminated));
|
||||||
|
s2_free_event(event);
|
||||||
|
|
||||||
|
nua_handle_destroy(nh);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
|
TCase *fetch_tcase(void)
|
||||||
|
{
|
||||||
|
TCase *tc = tcase_create("6.2 - Event fetch");
|
||||||
|
tcase_add_checked_fixture(tc, s2_dialog_setup, s2_dialog_teardown);
|
||||||
|
{
|
||||||
|
tcase_add_test(tc, fetch_6_2_1);
|
||||||
|
tcase_add_test(tc, fetch_6_2_2);
|
||||||
|
tcase_add_test(tc, fetch_6_2_3);
|
||||||
|
}
|
||||||
|
return tc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ====================================================================== */
|
||||||
|
|
||||||
|
/* Test case template */
|
||||||
|
|
||||||
|
START_TEST(empty)
|
||||||
|
{
|
||||||
|
s2_case("0.0.0", "Empty test case",
|
||||||
|
"Detailed explanation for empty test case.");
|
||||||
|
|
||||||
|
tport_set_params(s2->master, TPTAG_LOG(1), TAG_END());
|
||||||
|
s2_setup_logs(7);
|
||||||
|
s2_setup_logs(0);
|
||||||
|
tport_set_params(s2->master, TPTAG_LOG(0), TAG_END());
|
||||||
|
}
|
||||||
|
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
static TCase *empty_tcase(void)
|
||||||
|
{
|
||||||
|
TCase *tc = tcase_create("0 - Empty");
|
||||||
|
tcase_add_checked_fixture(tc, s2_dialog_setup, s2_dialog_teardown);
|
||||||
|
tcase_add_test(tc, empty);
|
||||||
|
|
||||||
|
return tc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ====================================================================== */
|
||||||
|
|
||||||
|
void check_simple_cases(Suite *suite)
|
||||||
|
{
|
||||||
|
suite_add_tcase(suite, subscribe_tcase());
|
||||||
|
suite_add_tcase(suite, fetch_tcase());
|
||||||
|
|
||||||
|
if (0) /* Template */
|
||||||
|
suite_add_tcase(suite, empty_tcase());
|
||||||
|
}
|
||||||
|
|
@ -42,6 +42,11 @@ _sips._udp SRV 3 100 5061 sip00
|
|||||||
SRV 4 50 5051 sip02
|
SRV 4 50 5051 sip02
|
||||||
SRV 5 10 5061 sip01
|
SRV 5 10 5061 sip01
|
||||||
|
|
||||||
|
cloop CNAME cloop0
|
||||||
|
cloop0 CNAME cloop1
|
||||||
|
cloop1 CNAME cloop2
|
||||||
|
cloop2 CNAME cloop0
|
||||||
|
|
||||||
sip CNAME sip00
|
sip CNAME sip00
|
||||||
|
|
||||||
subnet A6 0 3ff0:0::
|
subnet A6 0 3ff0:0::
|
||||||
|
@ -495,7 +495,9 @@ static int sres_decode_msg(sres_resolver_t *res,
|
|||||||
|
|
||||||
static char const *sres_toplevel(char buf[], size_t bsize, char const *domain);
|
static char const *sres_toplevel(char buf[], size_t bsize, char const *domain);
|
||||||
|
|
||||||
static sres_record_t *sres_create_record(sres_resolver_t *, sres_message_t *m);
|
static sres_record_t *sres_create_record(sres_resolver_t *,
|
||||||
|
sres_message_t *m,
|
||||||
|
int nth);
|
||||||
|
|
||||||
static sres_record_t *sres_init_rr_soa(sres_cache_t *cache,
|
static sres_record_t *sres_init_rr_soa(sres_cache_t *cache,
|
||||||
sres_soa_record_t *,
|
sres_soa_record_t *,
|
||||||
@ -3539,7 +3541,7 @@ sres_decode_msg(sres_resolver_t *res,
|
|||||||
|
|
||||||
total = errorcount + m->m_ancount + m->m_nscount + m->m_arcount;
|
total = errorcount + m->m_ancount + m->m_nscount + m->m_arcount;
|
||||||
|
|
||||||
answers = su_zalloc(chome, (total + 1) * sizeof answers[0]);
|
answers = su_zalloc(chome, (total + 2) * sizeof answers[0]);
|
||||||
if (!answers)
|
if (!answers)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -3548,7 +3550,7 @@ sres_decode_msg(sres_resolver_t *res,
|
|||||||
if (i < errorcount)
|
if (i < errorcount)
|
||||||
rr = error = sres_create_error_rr(res->res_cache, query, err);
|
rr = error = sres_create_error_rr(res->res_cache, query, err);
|
||||||
else
|
else
|
||||||
rr = sres_create_record(res, m);
|
rr = sres_create_record(res, m, i - errorcount);
|
||||||
|
|
||||||
if (!rr) {
|
if (!rr) {
|
||||||
SU_DEBUG_5(("sres_create_record: %s\n", m->m_error));
|
SU_DEBUG_5(("sres_create_record: %s\n", m->m_error));
|
||||||
@ -3565,12 +3567,31 @@ sres_decode_msg(sres_resolver_t *res,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (i < total) {
|
if (i < total) {
|
||||||
|
SU_DEBUG_5(("sres_decode_msg: %s\n", "less records than promised"));
|
||||||
for (i = 0; i < total; i++)
|
for (i = 0; i < total; i++)
|
||||||
sres_cache_free_record(res->res_cache, answers[i]);
|
sres_cache_free_record(res->res_cache, answers[i]);
|
||||||
su_free(chome, answers);
|
su_free(chome, answers);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m->m_ancount > 0 && errorcount == 0 && query->q_type < sres_qtype_tsig) {
|
||||||
|
char b0[8], b1[8];
|
||||||
|
for (i = 0; i < m->m_ancount; i++) {
|
||||||
|
if (query->q_type == answers[i]->sr_type)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == m->m_ancount) {
|
||||||
|
/* The queried request was not found. CNAME? */
|
||||||
|
SU_DEBUG_5(("sres_decode_msg: sent query %s, got %s\n",
|
||||||
|
sres_record_type(query->q_type, b0),
|
||||||
|
sres_record_type(answers[0]->sr_type, b1)));
|
||||||
|
rr = sres_create_error_rr(res->res_cache, query, err = SRES_RECORD_ERR);
|
||||||
|
memmove(answers + 1, answers, (sizeof answers[0]) * total++);
|
||||||
|
answers[errorcount++] = rr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < total; i++) {
|
for (i = 0; i < total; i++) {
|
||||||
rr = answers[i];
|
rr = answers[i];
|
||||||
|
|
||||||
@ -3591,7 +3612,7 @@ sres_decode_msg(sres_resolver_t *res,
|
|||||||
|
|
||||||
static
|
static
|
||||||
sres_record_t *
|
sres_record_t *
|
||||||
sres_create_record(sres_resolver_t *res, sres_message_t *m)
|
sres_create_record(sres_resolver_t *res, sres_message_t *m, int nth)
|
||||||
{
|
{
|
||||||
sres_cache_t *cache = res->res_cache;
|
sres_cache_t *cache = res->res_cache;
|
||||||
sres_record_t *sr, sr0[1];
|
sres_record_t *sr, sr0[1];
|
||||||
@ -3614,7 +3635,11 @@ sres_create_record(sres_resolver_t *res, sres_message_t *m)
|
|||||||
|
|
||||||
name[len] = 0;
|
name[len] = 0;
|
||||||
|
|
||||||
SU_DEBUG_9(("RR received %s %s %s %d rdlen=%d\n", name,
|
SU_DEBUG_9(("%s RR received %s %s %s %d rdlen=%d\n",
|
||||||
|
nth < m->m_ancount ? "ANSWER" :
|
||||||
|
nth < m->m_ancount + m->m_nscount ? "AUTHORITY" :
|
||||||
|
"ADDITIONAL",
|
||||||
|
name,
|
||||||
sres_record_type(sr->sr_type, btype),
|
sres_record_type(sr->sr_type, btype),
|
||||||
sres_record_class(sr->sr_class, bclass),
|
sres_record_class(sr->sr_class, bclass),
|
||||||
sr->sr_ttl, sr->sr_rdlen));
|
sr->sr_ttl, sr->sr_rdlen));
|
||||||
|
@ -169,15 +169,98 @@ void sres_cache_unref(sres_cache_t *cache)
|
|||||||
su_home_unref(cache->cache_home);
|
su_home_unref(cache->cache_home);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct frame {
|
||||||
|
struct frame *previous;
|
||||||
|
char const *domain;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Count or get matching records from cache */
|
||||||
|
static int
|
||||||
|
sres_cache_get0(sres_htable_t *htable,
|
||||||
|
sres_rr_hash_entry_t **iter,
|
||||||
|
uint16_t type,
|
||||||
|
char const *domain,
|
||||||
|
time_t now,
|
||||||
|
sres_record_t **cached,
|
||||||
|
int len,
|
||||||
|
struct frame *previous)
|
||||||
|
{
|
||||||
|
sres_cname_record_t *cname = NULL;
|
||||||
|
int dcount = 0, derrorcount = 0, ccount = 0;
|
||||||
|
|
||||||
|
for (; iter && *iter; iter = sres_htable_next(htable, iter)) {
|
||||||
|
sres_record_t *rr = (*iter)->rr;
|
||||||
|
|
||||||
|
if (rr == NULL)
|
||||||
|
continue;
|
||||||
|
if (now > (*iter)->rr_expires)
|
||||||
|
continue;
|
||||||
|
if (rr->sr_name == NULL)
|
||||||
|
continue;
|
||||||
|
if (!su_casematch(rr->sr_name, domain))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (rr->sr_type == type || type == sres_qtype_any) {
|
||||||
|
if (rr->sr_status == SRES_RECORD_ERR && type == sres_qtype_any)
|
||||||
|
continue;
|
||||||
|
if (cached) {
|
||||||
|
if (dcount >= len)
|
||||||
|
return -1;
|
||||||
|
cached[dcount] = rr, rr->sr_refcount++;
|
||||||
|
}
|
||||||
|
dcount++;
|
||||||
|
if (rr->sr_status)
|
||||||
|
derrorcount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type != sres_type_cname && rr->sr_type == sres_type_cname) {
|
||||||
|
if (rr->sr_status == 0)
|
||||||
|
cname = rr->sr_cname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cname && dcount == derrorcount) {
|
||||||
|
/* Nothing found, trace CNAMEs */
|
||||||
|
struct frame *f, frame = { previous, domain };
|
||||||
|
unsigned hash = sres_hash_key(domain = cname->cn_cname);
|
||||||
|
|
||||||
|
if (cached) {
|
||||||
|
if (dcount >= len)
|
||||||
|
return -1;
|
||||||
|
cached[dcount] = (sres_record_t *)cname;
|
||||||
|
cname->cn_record->r_refcount++;
|
||||||
|
}
|
||||||
|
dcount++;
|
||||||
|
|
||||||
|
/* Check for cname loops */
|
||||||
|
for (f = previous; f; f = f->previous) {
|
||||||
|
if (su_casematch(domain, f->domain))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f == NULL) {
|
||||||
|
ccount = sres_cache_get0(htable, sres_htable_hash(htable, hash),
|
||||||
|
type, domain, now,
|
||||||
|
cached ? cached + dcount : NULL,
|
||||||
|
cached ? len - dcount : 0,
|
||||||
|
&frame);
|
||||||
|
}
|
||||||
|
if (ccount < 0)
|
||||||
|
return ccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dcount + ccount;
|
||||||
|
}
|
||||||
|
|
||||||
/** Get a list of matching records from cache. */
|
/** Get a list of matching records from cache. */
|
||||||
int sres_cache_get(sres_cache_t *cache,
|
int sres_cache_get(sres_cache_t *cache,
|
||||||
uint16_t type,
|
uint16_t type,
|
||||||
char const *domain,
|
char const *domain,
|
||||||
sres_record_t ***return_cached)
|
sres_record_t ***return_cached)
|
||||||
{
|
{
|
||||||
sres_record_t **result = NULL, *rr = NULL;
|
sres_record_t **result = NULL;
|
||||||
sres_rr_hash_entry_t **rr_iter, **rr_iter2;
|
sres_rr_hash_entry_t **slot;
|
||||||
int result_size, rr_count = 0;
|
int result_size, i, j;
|
||||||
unsigned hash;
|
unsigned hash;
|
||||||
time_t now;
|
time_t now;
|
||||||
char b[8];
|
char b[8];
|
||||||
@ -198,28 +281,16 @@ int sres_cache_get(sres_cache_t *cache,
|
|||||||
time(&now);
|
time(&now);
|
||||||
|
|
||||||
/* First pass: just count the number of rr:s for array allocation */
|
/* First pass: just count the number of rr:s for array allocation */
|
||||||
rr_iter2 = sres_htable_hash(cache->cache_hash, hash);
|
slot = sres_htable_hash(cache->cache_hash, hash);
|
||||||
|
|
||||||
/* Find the domain records from the hash table */
|
i = sres_cache_get0(cache->cache_hash, slot, type, domain, now,
|
||||||
for (rr_iter = rr_iter2;
|
NULL, 0, NULL);
|
||||||
rr_iter && *rr_iter;
|
if (i <= 0) {
|
||||||
rr_iter = sres_htable_next(cache->cache_hash, rr_iter)) {
|
|
||||||
rr = (*rr_iter)->rr;
|
|
||||||
|
|
||||||
if (rr != NULL &&
|
|
||||||
now <= (*rr_iter)->rr_expires &&
|
|
||||||
(type == sres_qtype_any || rr->sr_type == type) &&
|
|
||||||
rr->sr_name != NULL &&
|
|
||||||
su_casematch(rr->sr_name, domain))
|
|
||||||
rr_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rr_count == 0) {
|
|
||||||
UNLOCK(cache);
|
UNLOCK(cache);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
result_size = (sizeof *result) * (rr_count + 1);
|
result_size = (sizeof *result) * (i + 1);
|
||||||
result = su_zalloc(cache->cache_home, result_size);
|
result = su_zalloc(cache->cache_home, result_size);
|
||||||
if (result == NULL) {
|
if (result == NULL) {
|
||||||
UNLOCK(cache);
|
UNLOCK(cache);
|
||||||
@ -227,35 +298,30 @@ int sres_cache_get(sres_cache_t *cache,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Second pass: add the rr pointers to the allocated array */
|
/* Second pass: add the rr pointers to the allocated array */
|
||||||
|
j = sres_cache_get0(cache->cache_hash, slot, type, domain, now,
|
||||||
for (rr_iter = rr_iter2, rr_count = 0;
|
result, i, NULL);
|
||||||
rr_iter && *rr_iter;
|
if (i != j) {
|
||||||
rr_iter = sres_htable_next(cache->cache_hash, rr_iter)) {
|
/* Uh-oh. */
|
||||||
rr = (*rr_iter)->rr;
|
SU_DEBUG_9(("%s(%p, %s, \"%s\") got %d != %d\n", "sres_cache_get",
|
||||||
|
(void *)cache, sres_record_type(type, b), domain, i, j));
|
||||||
if (rr != NULL &&
|
for (i = 0; i < result_size; i++) {
|
||||||
now <= (*rr_iter)->rr_expires &&
|
if (result[i])
|
||||||
(type == sres_qtype_any || rr->sr_type == type) &&
|
result[i]->sr_refcount--;
|
||||||
rr->sr_name != NULL &&
|
|
||||||
su_casematch(rr->sr_name, domain)) {
|
|
||||||
SU_DEBUG_9(("rr found in cache: %s %02d\n",
|
|
||||||
rr->sr_name, rr->sr_type));
|
|
||||||
|
|
||||||
result[rr_count++] = rr;
|
|
||||||
rr->sr_refcount++;
|
|
||||||
}
|
}
|
||||||
|
su_free(cache->cache_home, result);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
result[rr_count] = NULL;
|
result[i] = NULL;
|
||||||
|
|
||||||
UNLOCK(cache);
|
UNLOCK(cache);
|
||||||
|
|
||||||
SU_DEBUG_9(("%s(%p, %s, \"%s\") returned %d entries\n", "sres_cache_get",
|
SU_DEBUG_9(("%s(%p, %s, \"%s\") returned %d entries\n", "sres_cache_get",
|
||||||
(void *)cache, sres_record_type(type, b), domain, rr_count));
|
(void *)cache, sres_record_type(type, b), domain, i));
|
||||||
|
|
||||||
*return_cached = result;
|
*return_cached = result;
|
||||||
|
|
||||||
return rr_count;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
sres_record_t *
|
sres_record_t *
|
||||||
|
@ -90,6 +90,10 @@ typedef unsigned _int32 uint32_t;
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <sofia-sip/su_log.h>
|
||||||
|
|
||||||
|
extern su_log_t sresolv_log[];
|
||||||
|
|
||||||
char const name[] = "test_sresolv";
|
char const name[] = "test_sresolv";
|
||||||
|
|
||||||
struct sres_context_s
|
struct sres_context_s
|
||||||
@ -982,24 +986,133 @@ int test_srv(sres_context_t *ctx)
|
|||||||
int test_cname(sres_context_t *ctx)
|
int test_cname(sres_context_t *ctx)
|
||||||
{
|
{
|
||||||
sres_resolver_t *res = ctx->resolver;
|
sres_resolver_t *res = ctx->resolver;
|
||||||
sres_record_t **result;
|
sres_record_t **result, *sr;
|
||||||
const sres_cname_record_t *rr;
|
const sres_cname_record_t *cn;
|
||||||
char const *domain = "sip.example.com";
|
char const *domain = "sip.example.com";
|
||||||
|
|
||||||
BEGIN();
|
BEGIN();
|
||||||
|
|
||||||
|
TEST_1(sres_query(res, test_answer, ctx, sres_type_naptr, domain));
|
||||||
|
TEST_RUN(ctx);
|
||||||
|
|
||||||
|
TEST_1(result = ctx->result);
|
||||||
|
TEST_1(sr = result[0]);
|
||||||
|
TEST_1(sr->sr_record->r_status == SRES_RECORD_ERR);
|
||||||
|
TEST_1(cn = result[1]->sr_cname);
|
||||||
|
TEST(cn->cn_record->r_class, sres_class_in);
|
||||||
|
TEST(cn->cn_record->r_type, sres_type_cname);
|
||||||
|
TEST(cn->cn_record->r_ttl, 60);
|
||||||
|
TEST_S(cn->cn_cname, "sip00.example.com.");
|
||||||
|
|
||||||
|
sres_free_answers(res, ctx->result), ctx->result = NULL;
|
||||||
|
|
||||||
|
TEST_1(result = sres_cached_answers(res, sres_type_naptr, domain));
|
||||||
|
TEST_1(sr = result[0]);
|
||||||
|
TEST_1(sr->sr_record->r_status == SRES_RECORD_ERR);
|
||||||
|
TEST_1(cn = result[1]->sr_cname);
|
||||||
|
TEST(cn->cn_record->r_class, sres_class_in);
|
||||||
|
TEST(cn->cn_record->r_type, sres_type_cname);
|
||||||
|
TEST(cn->cn_record->r_ttl, 60);
|
||||||
|
TEST_S(cn->cn_cname, "sip00.example.com.");
|
||||||
|
|
||||||
|
sres_free_answers(res, result), ctx->result = NULL;
|
||||||
|
|
||||||
|
TEST_1(result = sres_cached_answers(res, sres_qtype_any, domain));
|
||||||
|
TEST_1(cn = result[0]->sr_cname);
|
||||||
|
TEST(cn->cn_record->r_class, sres_class_in);
|
||||||
|
TEST(cn->cn_record->r_type, sres_type_cname);
|
||||||
|
TEST(cn->cn_record->r_ttl, 60);
|
||||||
|
TEST_S(cn->cn_cname, "sip00.example.com.");
|
||||||
|
/* We might have A record, or then not */
|
||||||
|
|
||||||
|
sres_free_answers(res, result), ctx->result = NULL;
|
||||||
|
|
||||||
TEST_1(sres_query(res, test_answer, ctx, sres_type_a, domain));
|
TEST_1(sres_query(res, test_answer, ctx, sres_type_a, domain));
|
||||||
TEST_RUN(ctx);
|
TEST_RUN(ctx);
|
||||||
|
|
||||||
TEST_1(result = ctx->result);
|
TEST_1(result = ctx->result);
|
||||||
TEST_1(rr = result[0]->sr_cname);
|
TEST_1(cn = result[0]->sr_cname);
|
||||||
TEST(rr->cn_record->r_class, sres_class_in);
|
TEST(cn->cn_record->r_class, sres_class_in);
|
||||||
TEST(rr->cn_record->r_type, sres_type_cname);
|
TEST(cn->cn_record->r_type, sres_type_cname);
|
||||||
TEST(rr->cn_record->r_ttl, 60);
|
TEST(cn->cn_record->r_ttl, 60);
|
||||||
TEST_S(rr->cn_cname, "sip00.example.com.");
|
TEST_S(cn->cn_cname, "sip00.example.com.");
|
||||||
|
TEST_1(sr = result[1]);
|
||||||
|
TEST(sr->sr_record->r_class, sres_class_in);
|
||||||
|
TEST(sr->sr_record->r_type, sres_type_a);
|
||||||
|
|
||||||
sres_free_answers(res, ctx->result), ctx->result = NULL;
|
sres_free_answers(res, ctx->result), ctx->result = NULL;
|
||||||
|
|
||||||
|
TEST_1(result = sres_cached_answers(res, sres_type_a, domain));
|
||||||
|
TEST_1(cn = result[0]->sr_cname);
|
||||||
|
TEST(cn->cn_record->r_class, sres_class_in);
|
||||||
|
TEST(cn->cn_record->r_type, sres_type_cname);
|
||||||
|
TEST(cn->cn_record->r_ttl, 60);
|
||||||
|
TEST_S(cn->cn_cname, "sip00.example.com.");
|
||||||
|
TEST_1(sr = result[1]);
|
||||||
|
TEST(sr->sr_record->r_class, sres_class_in);
|
||||||
|
TEST(sr->sr_record->r_type, sres_type_a);
|
||||||
|
|
||||||
|
sres_free_answers(res, result);
|
||||||
|
|
||||||
|
domain = "cloop.example.com";
|
||||||
|
|
||||||
|
TEST_1(sres_query(res, test_answer, ctx, sres_type_a, domain));
|
||||||
|
TEST_RUN(ctx);
|
||||||
|
|
||||||
|
TEST_1(result = ctx->result);
|
||||||
|
TEST_1(sr = result[0]);
|
||||||
|
TEST_1(sr->sr_record->r_status == SRES_RECORD_ERR);
|
||||||
|
TEST_1(cn = result[1]->sr_cname);
|
||||||
|
TEST(cn->cn_record->r_class, sres_class_in);
|
||||||
|
TEST(cn->cn_record->r_type, sres_type_cname);
|
||||||
|
TEST(cn->cn_record->r_ttl, 60);
|
||||||
|
TEST_S(cn->cn_cname, "cloop0.example.com.");
|
||||||
|
TEST_1(cn = result[2]->sr_cname);
|
||||||
|
TEST(cn->cn_record->r_class, sres_class_in);
|
||||||
|
TEST(cn->cn_record->r_type, sres_type_cname);
|
||||||
|
TEST(cn->cn_record->r_ttl, 60);
|
||||||
|
TEST_S(cn->cn_cname, "cloop1.example.com.");
|
||||||
|
TEST_1(cn = result[3]->sr_cname);
|
||||||
|
TEST(cn->cn_record->r_class, sres_class_in);
|
||||||
|
TEST(cn->cn_record->r_type, sres_type_cname);
|
||||||
|
TEST(cn->cn_record->r_ttl, 60);
|
||||||
|
TEST_S(cn->cn_cname, "cloop2.example.com.");
|
||||||
|
TEST_1(cn = result[4]->sr_cname);
|
||||||
|
TEST(cn->cn_record->r_class, sres_class_in);
|
||||||
|
TEST(cn->cn_record->r_type, sres_type_cname);
|
||||||
|
TEST(cn->cn_record->r_ttl, 60);
|
||||||
|
TEST_S(cn->cn_cname, "cloop0.example.com.");
|
||||||
|
TEST_1(result[5] == NULL);
|
||||||
|
|
||||||
|
sres_free_answers(res, ctx->result), ctx->result = NULL;
|
||||||
|
|
||||||
|
TEST_1(result = sres_cached_answers(res, sres_type_a, domain));
|
||||||
|
TEST_1(sr = result[0]);
|
||||||
|
TEST_1(sr->sr_record->r_status == SRES_RECORD_ERR);
|
||||||
|
TEST_1(cn = result[1]->sr_cname);
|
||||||
|
TEST(cn->cn_record->r_class, sres_class_in);
|
||||||
|
TEST(cn->cn_record->r_type, sres_type_cname);
|
||||||
|
TEST(cn->cn_record->r_ttl, 60);
|
||||||
|
TEST_S(cn->cn_cname, "cloop0.example.com.");
|
||||||
|
TEST_1(cn = result[2]->sr_cname);
|
||||||
|
TEST(cn->cn_record->r_class, sres_class_in);
|
||||||
|
TEST(cn->cn_record->r_type, sres_type_cname);
|
||||||
|
TEST(cn->cn_record->r_ttl, 60);
|
||||||
|
TEST_S(cn->cn_cname, "cloop1.example.com.");
|
||||||
|
TEST_1(cn = result[3]->sr_cname);
|
||||||
|
TEST(cn->cn_record->r_class, sres_class_in);
|
||||||
|
TEST(cn->cn_record->r_type, sres_type_cname);
|
||||||
|
TEST(cn->cn_record->r_ttl, 60);
|
||||||
|
TEST_S(cn->cn_cname, "cloop2.example.com.");
|
||||||
|
TEST_1(cn = result[4]->sr_cname);
|
||||||
|
TEST(cn->cn_record->r_class, sres_class_in);
|
||||||
|
TEST(cn->cn_record->r_type, sres_type_cname);
|
||||||
|
TEST(cn->cn_record->r_ttl, 60);
|
||||||
|
TEST_S(cn->cn_cname, "cloop0.example.com.");
|
||||||
|
TEST_1(result[5] == NULL);
|
||||||
|
|
||||||
|
sres_free_answers(res, result);
|
||||||
|
|
||||||
END();
|
END();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1892,10 +2005,6 @@ void usage(int exitcode)
|
|||||||
exit(exitcode);
|
exit(exitcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <sofia-sip/su_log.h>
|
|
||||||
|
|
||||||
extern su_log_t sresolv_log[];
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user