1340 lines
41 KiB
C
1340 lines
41 KiB
C
/*
|
|
* This file is part of the Sofia-SIP package
|
|
*
|
|
* Copyright (C) 2005 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 test_soa.c
|
|
* @brief High-level tester for Sofia SDP Offer/Answer Engine
|
|
*
|
|
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
|
*
|
|
* @date Created: Wed Aug 17 12:12:12 EEST 2005 ppessi
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#if HAVE_ALARM
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#endif
|
|
|
|
struct context;
|
|
#define SOA_MAGIC_T struct context
|
|
|
|
#include "sofia-sip/soa.h"
|
|
#include "sofia-sip/soa_tag.h"
|
|
#include "sofia-sip/soa_add.h"
|
|
|
|
#include <sofia-sip/sdp.h>
|
|
|
|
#include <sofia-sip/su_log.h>
|
|
#include <sofia-sip/sip_tag.h>
|
|
|
|
extern su_log_t soa_log[];
|
|
|
|
char const name[] = "test_soa";
|
|
int tstflags = 0;
|
|
#define TSTFLAGS tstflags
|
|
|
|
#include <sofia-sip/tstdef.h>
|
|
|
|
#if HAVE_FUNC
|
|
#elif HAVE_FUNCTION
|
|
#define __func__ __FUNCTION__
|
|
#else
|
|
#define __func__ name
|
|
#endif
|
|
|
|
#define NONE ((void*)-1)
|
|
|
|
struct context
|
|
{
|
|
su_home_t home[1];
|
|
su_root_t *root;
|
|
|
|
struct {
|
|
soa_session_t *a;
|
|
soa_session_t *b;
|
|
} asynch;
|
|
|
|
soa_session_t *a;
|
|
soa_session_t *b;
|
|
|
|
soa_session_t *completed;
|
|
};
|
|
|
|
int test_api_completed(struct context *arg, soa_session_t *session)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int test_api_errors(struct context *ctx)
|
|
{
|
|
BEGIN();
|
|
|
|
char const *phrase = NULL;
|
|
char const *null = NULL;
|
|
|
|
TEST_1(!soa_create("default", NULL, NULL));
|
|
TEST_1(!soa_clone(NULL, NULL, NULL));
|
|
TEST_VOID(soa_destroy(NULL));
|
|
|
|
TEST_1(-1 == soa_set_params(NULL, TAG_END()));
|
|
TEST_1(-1 == soa_get_params(NULL, TAG_END()));
|
|
|
|
TEST_1(!soa_get_paramlist(NULL, TAG_END()));
|
|
|
|
TEST(soa_error_as_sip_response(NULL, &phrase), 500);
|
|
TEST_S(phrase, "Internal Server Error");
|
|
|
|
TEST_1(soa_error_as_sip_reason(NULL));
|
|
|
|
TEST_1(!soa_media_features(NULL, 0, NULL));
|
|
|
|
TEST_1(!soa_sip_require(NULL));
|
|
TEST_1(!soa_sip_supported(NULL));
|
|
|
|
TEST_1(-1 == soa_remote_sip_features(NULL, &null, &null));
|
|
|
|
TEST_1(soa_set_capability_sdp(NULL, NULL, NULL, -1) < 0);
|
|
TEST_1(soa_set_remote_sdp(NULL, NULL, NULL, -1) < 0);
|
|
TEST_1(soa_set_user_sdp(NULL, NULL, NULL, -1) < 0);
|
|
|
|
TEST_1(soa_get_capability_sdp(NULL, NULL, NULL, NULL) < 0);
|
|
TEST_1(soa_get_remote_sdp(NULL, NULL, NULL, NULL) < 0);
|
|
TEST_1(soa_get_user_sdp(NULL, NULL, NULL, NULL) < 0);
|
|
TEST_1(soa_get_local_sdp(NULL, NULL, NULL, NULL) < 0);
|
|
|
|
TEST_1(-1 == soa_generate_offer(NULL, 0, test_api_completed));
|
|
|
|
TEST_1(-1 == soa_generate_answer(NULL, test_api_completed));
|
|
|
|
TEST_1(-1 == soa_process_answer(NULL, test_api_completed));
|
|
|
|
TEST_1(-1 == soa_process_reject(NULL, test_api_completed));
|
|
|
|
TEST(soa_activate(NULL, "both"), -1);
|
|
TEST(soa_deactivate(NULL, "both"), -1);
|
|
TEST_VOID(soa_terminate(NULL, "both"));
|
|
|
|
TEST_1(!soa_is_complete(NULL));
|
|
|
|
TEST_1(!soa_init_offer_answer(NULL));
|
|
|
|
TEST(soa_is_audio_active(NULL), SOA_ACTIVE_DISABLED);
|
|
TEST(soa_is_video_active(NULL), SOA_ACTIVE_DISABLED);
|
|
TEST(soa_is_image_active(NULL), SOA_ACTIVE_DISABLED);
|
|
TEST(soa_is_chat_active(NULL), SOA_ACTIVE_DISABLED);
|
|
|
|
TEST(soa_is_remote_audio_active(NULL), SOA_ACTIVE_DISABLED);
|
|
TEST(soa_is_remote_video_active(NULL), SOA_ACTIVE_DISABLED);
|
|
TEST(soa_is_remote_image_active(NULL), SOA_ACTIVE_DISABLED);
|
|
TEST(soa_is_remote_chat_active(NULL), SOA_ACTIVE_DISABLED);
|
|
|
|
END();
|
|
}
|
|
|
|
int test_soa_tags(struct context *ctx)
|
|
{
|
|
BEGIN();
|
|
|
|
su_home_t home[1] = { SU_HOME_INIT(home) };
|
|
tagi_t *t;
|
|
|
|
tagi_t const soafilter[] = {
|
|
{ TAG_FILTER(soa_tag_filter) },
|
|
{ TAG_NULL() }
|
|
};
|
|
|
|
t = tl_filtered_tlist(home, soafilter,
|
|
SIPTAG_FROM_STR("sip:my.domain"),
|
|
SOATAG_USER_SDP_STR("v=0"),
|
|
SOATAG_HOLD("*"),
|
|
TAG_END());
|
|
TEST_1(t);
|
|
TEST_P(t[0].t_tag, soatag_user_sdp_str);
|
|
TEST_P(t[1].t_tag, soatag_hold);
|
|
TEST_1(t[2].t_tag == NULL || t[2].t_tag == tag_null);
|
|
|
|
su_home_deinit(home);
|
|
|
|
END();
|
|
}
|
|
|
|
int test_init(struct context *ctx, char *argv[])
|
|
{
|
|
BEGIN();
|
|
|
|
int n;
|
|
|
|
ctx->root = su_root_create(ctx); TEST_1(ctx->root);
|
|
|
|
ctx->asynch.a = soa_create("asynch", ctx->root, ctx);
|
|
TEST_1(!ctx->asynch.a);
|
|
|
|
#if 0
|
|
TEST_1(!soa_find("asynch"));
|
|
TEST_1(soa_find("default"));
|
|
|
|
n = soa_add("asynch", &soa_asynch_actions); TEST(n, 0);
|
|
|
|
TEST_1(soa_find("asynch"));
|
|
|
|
ctx->asynch.a = soa_create("asynch", ctx->root, ctx);
|
|
TEST_1(ctx->asynch.a);
|
|
|
|
ctx->asynch.b = soa_create("asynch", ctx->root, ctx);
|
|
TEST_1(ctx->asynch.b);
|
|
#endif
|
|
|
|
/* Create asynchronous endpoints */
|
|
|
|
ctx->a = soa_create("static", ctx->root, ctx);
|
|
TEST_1(!ctx->a);
|
|
|
|
TEST_1(!soa_find("static"));
|
|
TEST_1(soa_find("default"));
|
|
|
|
n = soa_add("static", &soa_default_actions); TEST(n, 0);
|
|
|
|
TEST_1(soa_find("static"));
|
|
|
|
ctx->a = soa_create("static", ctx->root, ctx);
|
|
TEST_1(ctx->a);
|
|
|
|
ctx->b = soa_create("static", ctx->root, ctx);
|
|
TEST_1(ctx->b);
|
|
|
|
END();
|
|
}
|
|
|
|
int test_params(struct context *ctx)
|
|
{
|
|
BEGIN();
|
|
int n;
|
|
int af;
|
|
char const *address;
|
|
char const *hold;
|
|
int rtp_select, rtp_sort;
|
|
int rtp_mismatch;
|
|
int srtp_enable, srtp_confidentiality, srtp_integrity;
|
|
soa_session_t *a = ctx->a, *b = ctx->b;
|
|
|
|
n = soa_set_params(a, TAG_END()); TEST(n, 0);
|
|
n = soa_set_params(b, TAG_END()); TEST(n, 0);
|
|
|
|
af = -42;
|
|
address = NONE;
|
|
hold = NONE;
|
|
|
|
rtp_select = -1, rtp_sort = -1, rtp_mismatch = -1;
|
|
srtp_enable = -1, srtp_confidentiality = -1, srtp_integrity = -1;
|
|
|
|
TEST(soa_get_params(a,
|
|
SOATAG_AF_REF(af),
|
|
SOATAG_ADDRESS_REF(address),
|
|
SOATAG_HOLD_REF(hold),
|
|
|
|
SOATAG_RTP_SELECT_REF(rtp_select),
|
|
SOATAG_RTP_SORT_REF(rtp_sort),
|
|
SOATAG_RTP_MISMATCH_REF(rtp_mismatch),
|
|
|
|
SOATAG_SRTP_ENABLE_REF(srtp_enable),
|
|
SOATAG_SRTP_CONFIDENTIALITY_REF(srtp_confidentiality),
|
|
SOATAG_SRTP_INTEGRITY_REF(srtp_integrity),
|
|
TAG_END()),
|
|
9);
|
|
TEST(af, SOA_AF_ANY);
|
|
TEST_P(address, 0);
|
|
TEST_P(hold, 0);
|
|
TEST(rtp_select, SOA_RTP_SELECT_SINGLE);
|
|
TEST(rtp_sort, SOA_RTP_SORT_DEFAULT);
|
|
TEST(rtp_mismatch, 0);
|
|
TEST(srtp_enable, 0);
|
|
TEST(srtp_confidentiality, 0);
|
|
TEST(srtp_integrity, 0);
|
|
|
|
TEST(soa_set_params(a,
|
|
SOATAG_AF(SOA_AF_IP4_IP6),
|
|
SOATAG_ADDRESS("127.0.0.1"),
|
|
SOATAG_HOLD("audio"),
|
|
|
|
SOATAG_RTP_SELECT(SOA_RTP_SELECT_ALL),
|
|
SOATAG_RTP_SORT(SOA_RTP_SORT_LOCAL),
|
|
SOATAG_RTP_MISMATCH(1),
|
|
|
|
SOATAG_SRTP_ENABLE(1),
|
|
SOATAG_SRTP_CONFIDENTIALITY(1),
|
|
SOATAG_SRTP_INTEGRITY(1),
|
|
|
|
TAG_END()),
|
|
9);
|
|
TEST(soa_get_params(a,
|
|
SOATAG_AF_REF(af),
|
|
SOATAG_ADDRESS_REF(address),
|
|
SOATAG_HOLD_REF(hold),
|
|
|
|
SOATAG_RTP_SELECT_REF(rtp_select),
|
|
SOATAG_RTP_SORT_REF(rtp_sort),
|
|
SOATAG_RTP_MISMATCH_REF(rtp_mismatch),
|
|
|
|
SOATAG_SRTP_ENABLE_REF(srtp_enable),
|
|
SOATAG_SRTP_CONFIDENTIALITY_REF(srtp_confidentiality),
|
|
SOATAG_SRTP_INTEGRITY_REF(srtp_integrity),
|
|
TAG_END()),
|
|
9);
|
|
TEST(af, SOA_AF_IP4_IP6);
|
|
TEST_S(address, "127.0.0.1");
|
|
TEST_S(hold, "audio");
|
|
TEST(rtp_select, SOA_RTP_SELECT_ALL);
|
|
TEST(rtp_sort, SOA_RTP_SORT_LOCAL);
|
|
TEST(rtp_mismatch, 1);
|
|
TEST(srtp_enable, 1);
|
|
TEST(srtp_confidentiality, 1);
|
|
TEST(srtp_integrity, 1);
|
|
|
|
/* Restore defaults */
|
|
TEST(soa_set_params(a,
|
|
SOATAG_AF(SOA_AF_IP4_IP6),
|
|
SOATAG_ADDRESS(NULL),
|
|
SOATAG_HOLD(NULL),
|
|
|
|
SOATAG_RTP_SELECT(SOA_RTP_SELECT_SINGLE),
|
|
SOATAG_RTP_SORT(SOA_RTP_SORT_DEFAULT),
|
|
SOATAG_RTP_MISMATCH(0),
|
|
|
|
SOATAG_SRTP_ENABLE(0),
|
|
SOATAG_SRTP_CONFIDENTIALITY(0),
|
|
SOATAG_SRTP_INTEGRITY(0),
|
|
|
|
TAG_END()),
|
|
9);
|
|
|
|
END();
|
|
}
|
|
|
|
int test_completed(struct context *ctx, soa_session_t *session)
|
|
{
|
|
ctx->completed = session;
|
|
su_root_break(ctx->root);
|
|
return 0;
|
|
}
|
|
|
|
int test_static_offer_answer(struct context *ctx)
|
|
{
|
|
BEGIN();
|
|
int n;
|
|
|
|
soa_session_t *a, *b;
|
|
|
|
char const *caps = NONE, *offer = NONE, *answer = NONE;
|
|
isize_t capslen = -1, offerlen = -1, answerlen = -1;
|
|
|
|
su_home_t home[1] = { SU_HOME_INIT(home) };
|
|
|
|
char const a_caps[] =
|
|
"v=0\r\n"
|
|
"o=left 219498671 2 IN IP4 127.0.0.2\r\n"
|
|
"c=IN IP4 127.0.0.2\r\n"
|
|
"m=audio 0 RTP/AVP 0 8\r\n";
|
|
|
|
char const b_caps[] =
|
|
"m=audio 5004 RTP/AVP 96 8\n"
|
|
"m=rtpmap:96 GSM/8000\n";
|
|
|
|
TEST(soa_set_capability_sdp(ctx->a, 0, "m=audio 0 RTP/AVP 0 8", -1),
|
|
1);
|
|
TEST(soa_set_capability_sdp(ctx->a, 0, a_caps, strlen(a_caps)),
|
|
1);
|
|
TEST(soa_get_capability_sdp(ctx->a, NULL, &caps, &capslen), 1);
|
|
|
|
TEST_1(caps != NULL && caps != NONE);
|
|
TEST_1(capslen > 0);
|
|
|
|
TEST(soa_set_user_sdp(ctx->b, 0, b_caps, strlen(b_caps)), 1);
|
|
TEST(soa_get_capability_sdp(ctx->a, NULL, &caps, &capslen), 1);
|
|
|
|
TEST_1(a = soa_clone(ctx->a, ctx->root, ctx));
|
|
TEST_1(b = soa_clone(ctx->b, ctx->root, ctx));
|
|
|
|
n = soa_get_local_sdp(a, NULL, &offer, &offerlen); TEST(n, 0);
|
|
|
|
n = soa_set_user_sdp(a, 0, "m=audio 5004 RTP/AVP 0 8", -1); TEST(n, 1);
|
|
|
|
n = soa_generate_offer(a, 1, test_completed); TEST(n, 0);
|
|
|
|
n = soa_get_local_sdp(a, NULL, &offer, &offerlen); TEST(n, 1);
|
|
TEST_1(offer != NULL && offer != NONE);
|
|
|
|
n = soa_set_remote_sdp(b, 0, offer, offerlen); TEST(n, 1);
|
|
|
|
n = soa_get_local_sdp(b, NULL, &answer, &answerlen); TEST(n, 0);
|
|
|
|
n = soa_set_params(b,
|
|
SOATAG_LOCAL_SDP_STR("m=audio 5004 RTP/AVP 8"),
|
|
SOATAG_AF(SOA_AF_IP4_ONLY),
|
|
SOATAG_ADDRESS("1.2.3.4"),
|
|
TAG_END());
|
|
|
|
n = soa_generate_answer(b, test_completed); TEST(n, 0);
|
|
|
|
TEST_1(soa_is_complete(b));
|
|
TEST(soa_activate(b, NULL), 0);
|
|
|
|
n = soa_get_local_sdp(b, NULL, &answer, &answerlen); TEST(n, 1);
|
|
TEST_1(answer != NULL && answer != NONE);
|
|
TEST_1(strstr(answer, "c=IN IP4 1.2.3.4"));
|
|
|
|
n = soa_set_remote_sdp(a, 0, answer, -1); TEST(n, 1);
|
|
|
|
n = soa_process_answer(a, test_completed); TEST(n, 0);
|
|
|
|
TEST_1(soa_is_complete(a));
|
|
TEST(soa_activate(a, NULL), 0);
|
|
|
|
TEST(soa_is_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_video_active(a), SOA_ACTIVE_DISABLED);
|
|
TEST(soa_is_image_active(a), SOA_ACTIVE_DISABLED);
|
|
TEST(soa_is_chat_active(a), SOA_ACTIVE_DISABLED);
|
|
|
|
TEST(soa_is_remote_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_remote_video_active(a), SOA_ACTIVE_DISABLED);
|
|
TEST(soa_is_remote_image_active(a), SOA_ACTIVE_DISABLED);
|
|
TEST(soa_is_remote_chat_active(a), SOA_ACTIVE_DISABLED);
|
|
|
|
/* 'A' will put call on hold */
|
|
offer = NONE;
|
|
TEST(soa_set_params(a, SOATAG_HOLD("*"), TAG_END()), 1);
|
|
|
|
TEST(soa_generate_offer(a, 1, test_completed), 0);
|
|
TEST(soa_get_local_sdp(a, NULL, &offer, &offerlen), 1);
|
|
TEST_1(offer != NULL && offer != NONE);
|
|
TEST_1(strstr(offer, "a=sendonly"));
|
|
TEST(soa_set_remote_sdp(b, 0, offer, offerlen), 1);
|
|
TEST(soa_generate_answer(b, test_completed), 0);
|
|
TEST_1(soa_is_complete(b));
|
|
TEST(soa_activate(b, NULL), 0);
|
|
TEST(soa_get_local_sdp(b, NULL, &answer, &answerlen), 1);
|
|
TEST_1(answer != NULL && answer != NONE);
|
|
TEST_1(strstr(answer, "a=recvonly"));
|
|
TEST(soa_set_remote_sdp(a, 0, answer, -1), 1);
|
|
TEST(soa_process_answer(a, test_completed), 0);
|
|
TEST(soa_activate(a, NULL), 0);
|
|
|
|
TEST(soa_is_audio_active(a), SOA_ACTIVE_SENDONLY);
|
|
TEST(soa_is_remote_audio_active(a), SOA_ACTIVE_SENDONLY);
|
|
|
|
/* 'A' will release hold. */
|
|
TEST(soa_set_params(a, SOATAG_HOLD(NULL), TAG_END()), 1);
|
|
|
|
TEST(soa_generate_offer(a, 1, test_completed), 0);
|
|
TEST(soa_get_local_sdp(a, NULL, &offer, &offerlen), 1);
|
|
TEST_1(offer != NULL && offer != NONE);
|
|
TEST_1(!strstr(offer, "a=sendonly"));
|
|
TEST(soa_set_remote_sdp(b, 0, offer, offerlen), 1);
|
|
TEST(soa_generate_answer(b, test_completed), 0);
|
|
TEST_1(soa_is_complete(b));
|
|
TEST(soa_activate(b, NULL), 0);
|
|
TEST(soa_get_local_sdp(b, NULL, &answer, &answerlen), 1);
|
|
TEST_1(answer != NULL && answer != NONE);
|
|
TEST_1(!strstr(answer, "a=recvonly"));
|
|
TEST(soa_set_remote_sdp(a, 0, answer, -1), 1);
|
|
TEST(soa_process_answer(a, test_completed), 0);
|
|
TEST(soa_activate(a, NULL), 0);
|
|
|
|
TEST(soa_is_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_remote_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
|
|
/* 'A' will put B on hold but this time with c=IN IP4 0.0.0.0 */
|
|
TEST(soa_set_params(a, SOATAG_HOLD("*"), TAG_END()), 1);
|
|
TEST(soa_generate_offer(a, 1, test_completed), 0);
|
|
|
|
{
|
|
sdp_session_t const *o_sdp;
|
|
sdp_session_t *sdp;
|
|
sdp_printer_t *p;
|
|
sdp_connection_t *c;
|
|
|
|
TEST(soa_get_local_sdp(a, &o_sdp, NULL, NULL), 1);
|
|
TEST_1(o_sdp != NULL && o_sdp != NONE);
|
|
TEST_1(sdp = sdp_session_dup(home, o_sdp));
|
|
|
|
/* Remove mode, change c=, encode offer */
|
|
if (sdp->sdp_media->m_connections)
|
|
c = sdp->sdp_media->m_connections;
|
|
else
|
|
c = sdp->sdp_connection;
|
|
TEST_1(c);
|
|
c->c_address = "0.0.0.0";
|
|
|
|
TEST_1(p = sdp_print(home, sdp, NULL, 0, sdp_f_realloc));
|
|
TEST_1(sdp_message(p));
|
|
offer = sdp_message(p); offerlen = strlen(offer);
|
|
}
|
|
|
|
TEST(soa_set_remote_sdp(b, 0, offer, -1), 1);
|
|
TEST(soa_generate_answer(b, test_completed), 0);
|
|
TEST_1(soa_is_complete(b));
|
|
TEST(soa_activate(b, NULL), 0);
|
|
TEST(soa_get_local_sdp(b, NULL, &answer, &answerlen), 1);
|
|
TEST_1(answer != NULL && answer != NONE);
|
|
TEST_1(strstr(answer, "a=recvonly"));
|
|
TEST(soa_set_remote_sdp(a, 0, answer, -1), 1);
|
|
TEST(soa_process_answer(a, test_completed), 0);
|
|
TEST(soa_activate(a, NULL), 0);
|
|
|
|
TEST(soa_is_audio_active(a), SOA_ACTIVE_SENDONLY);
|
|
TEST(soa_is_remote_audio_active(a), SOA_ACTIVE_SENDONLY);
|
|
TEST(soa_is_audio_active(b), SOA_ACTIVE_RECVONLY);
|
|
TEST(soa_is_remote_audio_active(b), SOA_ACTIVE_RECVONLY);
|
|
|
|
/* 'A' will propose adding video. */
|
|
/* 'B' will reject. */
|
|
TEST(soa_set_params(a,
|
|
SOATAG_HOLD(NULL), /* 'A' will release hold. */
|
|
SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8\r\n"
|
|
"m=video 5006 RTP/AVP 34\r\n"),
|
|
TAG_END()), 2);
|
|
|
|
TEST(soa_generate_offer(a, 1, test_completed), 0);
|
|
TEST(soa_get_local_sdp(a, NULL, &offer, &offerlen), 1);
|
|
TEST_1(offer != NULL && offer != NONE);
|
|
TEST_1(!strstr(offer, "a=sendonly"));
|
|
TEST_1(strstr(offer, "m=video"));
|
|
TEST(soa_set_remote_sdp(b, 0, offer, offerlen), 1);
|
|
TEST(soa_generate_answer(b, test_completed), 0);
|
|
TEST_1(soa_is_complete(b));
|
|
TEST(soa_activate(b, NULL), 0);
|
|
TEST(soa_get_local_sdp(b, NULL, &answer, &answerlen), 1);
|
|
TEST_1(answer != NULL && answer != NONE);
|
|
TEST_1(!strstr(answer, "a=recvonly"));
|
|
TEST_1(strstr(answer, "m=video"));
|
|
TEST(soa_set_remote_sdp(a, 0, answer, -1), 1);
|
|
TEST(soa_process_answer(a, test_completed), 0);
|
|
TEST(soa_activate(a, NULL), 0);
|
|
|
|
TEST(soa_is_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_remote_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_video_active(a), SOA_ACTIVE_REJECTED);
|
|
|
|
{
|
|
/* Test tags */
|
|
sdp_session_t const *l = NULL, *u = NULL, *r = NULL;
|
|
sdp_media_t const *m;
|
|
|
|
TEST(soa_get_params(b,
|
|
SOATAG_LOCAL_SDP_REF(l),
|
|
SOATAG_USER_SDP_REF(u),
|
|
SOATAG_REMOTE_SDP_REF(r),
|
|
TAG_END()), 3);
|
|
|
|
TEST_1(l); TEST_1(u); TEST_1(r);
|
|
TEST_1(m = l->sdp_media); TEST(m->m_type, sdp_media_audio);
|
|
TEST_1(!m->m_rejected);
|
|
TEST_1(m = m->m_next); TEST(m->m_type, sdp_media_video);
|
|
TEST_1(m->m_rejected);
|
|
}
|
|
|
|
/* 'B' will now propose adding video. */
|
|
/* 'A' will accept. */
|
|
TEST(soa_set_params(b,
|
|
SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8\r\n"
|
|
"m=video 5006 RTP/AVP 34\r\n"),
|
|
TAG_END()), 1);
|
|
|
|
TEST(soa_generate_offer(b, 1, test_completed), 0);
|
|
TEST(soa_get_local_sdp(b, NULL, &offer, &offerlen), 1);
|
|
TEST_1(offer != NULL && offer != NONE);
|
|
TEST_1(!strstr(offer, "b=sendonly"));
|
|
TEST_1(strstr(offer, "m=video"));
|
|
TEST(soa_set_remote_sdp(a, 0, offer, offerlen), 1);
|
|
TEST(soa_generate_answer(a, test_completed), 0);
|
|
TEST_1(soa_is_complete(a));
|
|
TEST(soa_activate(a, NULL), 0);
|
|
TEST(soa_get_local_sdp(a, NULL, &answer, &answerlen), 1);
|
|
TEST_1(answer != NULL && answer != NONE);
|
|
TEST_1(!strstr(answer, "b=recvonly"));
|
|
TEST_1(strstr(answer, "m=video"));
|
|
TEST(soa_set_remote_sdp(b, 0, answer, -1), 1);
|
|
TEST(soa_process_answer(b, test_completed), 0);
|
|
TEST(soa_activate(b, NULL), 0);
|
|
|
|
TEST(soa_is_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_remote_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_video_active(a), SOA_ACTIVE_SENDRECV);
|
|
|
|
TEST_VOID(soa_terminate(a, NULL));
|
|
|
|
TEST(soa_is_audio_active(a), SOA_ACTIVE_DISABLED);
|
|
TEST(soa_is_remote_audio_active(a), SOA_ACTIVE_DISABLED);
|
|
|
|
TEST_VOID(soa_terminate(b, NULL));
|
|
|
|
TEST_VOID(soa_destroy(a));
|
|
TEST_VOID(soa_destroy(b));
|
|
|
|
su_home_deinit(home);
|
|
|
|
END();
|
|
}
|
|
|
|
int test_codec_selection(struct context *ctx)
|
|
{
|
|
BEGIN();
|
|
int n;
|
|
|
|
soa_session_t *a, *b;
|
|
|
|
char const *offer = NONE, *answer = NONE;
|
|
isize_t offerlen = -1, answerlen = -1;
|
|
|
|
sdp_session_t const *a_sdp, *b_sdp;
|
|
sdp_media_t const *m;
|
|
sdp_rtpmap_t const *rm;
|
|
|
|
char const a_caps[] =
|
|
"v=0\r\n"
|
|
"o=left 219498671 2 IN IP4 127.0.0.2\r\n"
|
|
"c=IN IP4 127.0.0.2\r\n"
|
|
"m=audio 5008 RTP/AVP 0 8 97\r\n"
|
|
"a=rtpmap:97 GSM/8000\n"
|
|
;
|
|
|
|
char const b_caps[] =
|
|
"m=audio 5004 RTP/AVP 96 97\n"
|
|
"a=rtpmap:96 G7231/8000\n"
|
|
"a=rtpmap:97 G729/8000\n";
|
|
|
|
TEST_1(a = soa_create("static", ctx->root, ctx));
|
|
TEST_1(b = soa_create("static", ctx->root, ctx));
|
|
|
|
TEST(soa_set_user_sdp(a, 0, a_caps, strlen(a_caps)), 1);
|
|
TEST(soa_set_user_sdp(b, 0, b_caps, strlen(b_caps)), 1);
|
|
|
|
TEST(soa_set_params(a, SOATAG_AUDIO_AUX("cn telephone-event"), TAG_END()), 1);
|
|
|
|
n = soa_generate_offer(a, 1, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(a, NULL, &offer, &offerlen); TEST(n, 1);
|
|
TEST_1(offer != NULL && offer != NONE);
|
|
n = soa_set_remote_sdp(b, 0, offer, offerlen); TEST(n, 1);
|
|
n = soa_get_local_sdp(b, NULL, &answer, &answerlen); TEST(n, 0);
|
|
n = soa_generate_answer(b, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(b, &b_sdp, &answer, &answerlen); TEST(n, 1);
|
|
TEST_1(answer != NULL && answer != NONE);
|
|
n = soa_set_remote_sdp(a, 0, answer, -1); TEST(n, 1);
|
|
n = soa_process_answer(a, test_completed); TEST(n, 0);
|
|
|
|
TEST_1(soa_is_complete(b));
|
|
TEST(soa_activate(b, NULL), 0);
|
|
|
|
TEST_1(soa_is_complete(a));
|
|
TEST(soa_activate(a, NULL), 0);
|
|
|
|
TEST(soa_is_audio_active(a), SOA_ACTIVE_REJECTED);
|
|
TEST(soa_is_remote_audio_active(a), SOA_ACTIVE_REJECTED);
|
|
|
|
TEST_1(m = b_sdp->sdp_media); TEST_1(m->m_rejected);
|
|
TEST_1(rm = m->m_rtpmaps); TEST(rm->rm_pt, 96);
|
|
TEST_S(rm->rm_encoding, "G7231");
|
|
/* Not using payload type 97 from offer */
|
|
TEST_1(rm = rm->rm_next); TEST(rm->rm_pt, 98);
|
|
TEST_S(rm->rm_encoding, "G729");
|
|
TEST_1(!rm->rm_next);
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/* Re-O/A: A generates new SDP */
|
|
n = soa_generate_offer(a, 1, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(a, &a_sdp, &offer, &offerlen); TEST(n, 1);
|
|
TEST_1(offer != NULL && offer != NONE);
|
|
n = soa_set_remote_sdp(b, 0, offer, offerlen); TEST(n, 1);
|
|
n = soa_generate_answer(b, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(b, &b_sdp, &answer, &answerlen); TEST(n, 1);
|
|
TEST_1(answer != NULL && answer != NONE);
|
|
n = soa_set_remote_sdp(a, 0, answer, -1); TEST(n, 0);
|
|
n = soa_process_answer(a, test_completed); TEST(n, 0);
|
|
|
|
TEST_1(soa_is_complete(b));
|
|
TEST(soa_activate(b, NULL), 0);
|
|
|
|
TEST_1(soa_is_complete(a));
|
|
TEST(soa_activate(a, NULL), 0);
|
|
|
|
/* Re-O/A: no-one regenerates new SDP */
|
|
n = soa_generate_offer(a, 1, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(a, &a_sdp, &offer, &offerlen); TEST(n, 1);
|
|
TEST_1(offer != NULL && offer != NONE);
|
|
n = soa_set_remote_sdp(b, 0, offer, offerlen); TEST(n, 0);
|
|
n = soa_generate_answer(b, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(b, &b_sdp, &answer, &answerlen); TEST(n, 1);
|
|
TEST_1(answer != NULL && answer != NONE);
|
|
n = soa_set_remote_sdp(a, 0, answer, -1); TEST(n, 0);
|
|
n = soa_process_answer(a, test_completed); TEST(n, 0);
|
|
|
|
TEST_1(soa_is_complete(b));
|
|
TEST(soa_activate(b, NULL), 0);
|
|
|
|
TEST_1(soa_is_complete(a));
|
|
TEST(soa_activate(a, NULL), 0);
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/* Re-O/A: accept media without common codecs */
|
|
|
|
/* Accept media without common codecs */
|
|
TEST_1(soa_set_params(a, SOATAG_RTP_MISMATCH(1), TAG_END()));
|
|
TEST_1(soa_set_params(b, SOATAG_RTP_MISMATCH(1), TAG_END()));
|
|
|
|
n = soa_generate_offer(a, 1, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(a, &a_sdp, &offer, &offerlen); TEST(n, 1);
|
|
TEST_1(offer != NULL && offer != NONE);
|
|
n = soa_set_remote_sdp(b, 0, offer, offerlen); TEST(n, 1);
|
|
n = soa_generate_answer(b, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(b, &b_sdp, &answer, &answerlen); TEST(n, 1);
|
|
TEST_1(answer != NULL && answer != NONE);
|
|
n = soa_set_remote_sdp(a, 0, answer, -1); TEST(n, 1);
|
|
n = soa_process_answer(a, test_completed); TEST(n, 0);
|
|
|
|
TEST_1(soa_is_complete(b));
|
|
TEST(soa_activate(b, NULL), 0);
|
|
|
|
TEST_1(soa_is_complete(a));
|
|
TEST(soa_activate(a, NULL), 0);
|
|
|
|
TEST(soa_is_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_remote_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
|
|
TEST_1(m = b_sdp->sdp_media); TEST_1(!m->m_rejected);
|
|
TEST_1(rm = m->m_rtpmaps); TEST(rm->rm_pt, 96);
|
|
TEST_S(rm->rm_encoding, "G7231");
|
|
/* Not using payload type 97 from offer */
|
|
TEST_1(rm = rm->rm_next); TEST(rm->rm_pt, 98);
|
|
TEST_S(rm->rm_encoding, "G729");
|
|
TEST_1(!rm->rm_next);
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/* Re-O/A: add a common codec */
|
|
|
|
/* Accept media without common codecs */
|
|
TEST_1(soa_set_params(a, SOATAG_RTP_MISMATCH(0),
|
|
SOATAG_USER_SDP_STR(
|
|
"v=0\r\n"
|
|
"o=left 219498671 2 IN IP4 127.0.0.2\r\n"
|
|
"c=IN IP4 127.0.0.2\r\n"
|
|
"m=audio 5008 RTP/AVP 0 8 96 3 127\r\n"
|
|
"a=rtpmap:96 G729/8000\n"
|
|
"a=rtpmap:127 CN/8000\n"
|
|
),
|
|
SOATAG_RTP_SORT(SOA_RTP_SORT_REMOTE),
|
|
SOATAG_RTP_SELECT(SOA_RTP_SELECT_ALL),
|
|
TAG_END()));
|
|
TEST_1(soa_set_params(b, SOATAG_RTP_MISMATCH(0),
|
|
SOATAG_USER_SDP_STR(
|
|
"v=0\r\n"
|
|
"o=left 219498671 2 IN IP4 127.0.0.2\r\n"
|
|
"c=IN IP4 127.0.0.2\r\n"
|
|
"m=audio 5004 RTP/AVP 96 3 97 111\r\n"
|
|
"a=rtpmap:96 G7231/8000\n"
|
|
"a=rtpmap:97 G729/8000\n"
|
|
"a=rtpmap:111 telephone-event/8000\n"
|
|
"a=fmtp:111 0-15\n"
|
|
),
|
|
SOATAG_AUDIO_AUX("cn telephone-event"),
|
|
SOATAG_RTP_SORT(SOA_RTP_SORT_LOCAL),
|
|
SOATAG_RTP_SELECT(SOA_RTP_SELECT_COMMON),
|
|
TAG_END()));
|
|
|
|
n = soa_generate_offer(a, 1, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(a, &a_sdp, &offer, &offerlen); TEST(n, 1);
|
|
TEST_1(offer != NULL && offer != NONE);
|
|
n = soa_set_remote_sdp(b, 0, offer, offerlen); TEST(n, 1);
|
|
n = soa_generate_answer(b, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(b, &b_sdp, &answer, &answerlen); TEST(n, 1);
|
|
TEST_1(answer != NULL && answer != NONE);
|
|
n = soa_set_remote_sdp(a, 0, answer, -1); TEST(n, 1);
|
|
n = soa_process_answer(a, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(a, &a_sdp, NULL, NULL); TEST(n, 1);
|
|
|
|
TEST_1(soa_is_complete(b));
|
|
TEST(soa_activate(b, NULL), 0);
|
|
|
|
TEST_1(soa_is_complete(a));
|
|
TEST(soa_activate(a, NULL), 0);
|
|
|
|
TEST(soa_is_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_remote_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
|
|
TEST_1(m = a_sdp->sdp_media); TEST_1(!m->m_rejected);
|
|
TEST_1(rm = m->m_rtpmaps); TEST(rm->rm_pt, 3);
|
|
TEST_S(rm->rm_encoding, "GSM");
|
|
TEST_1(rm = rm->rm_next); TEST(rm->rm_pt, 96);
|
|
TEST_S(rm->rm_encoding, "G729");
|
|
TEST_1(rm = rm->rm_next); TEST(rm->rm_pt, 0);
|
|
TEST_S(rm->rm_encoding, "PCMU");
|
|
TEST_1(rm = rm->rm_next); TEST(rm->rm_pt, 8);
|
|
TEST_S(rm->rm_encoding, "PCMA");
|
|
TEST_1(rm = rm->rm_next); TEST(rm->rm_pt, 127);
|
|
TEST_S(rm->rm_encoding, "CN");
|
|
TEST_1(!rm->rm_next);
|
|
|
|
TEST_1(m = b_sdp->sdp_media); TEST_1(!m->m_rejected);
|
|
TEST_1(rm = m->m_rtpmaps); TEST(rm->rm_pt, 3);
|
|
TEST_S(rm->rm_encoding, "GSM");
|
|
/* Using payload type 96 from offer */
|
|
TEST_1(rm = rm->rm_next); TEST(rm->rm_pt, 96);
|
|
TEST_S(rm->rm_encoding, "G729");
|
|
TEST_1(rm = rm->rm_next); TEST(rm->rm_pt, 111);
|
|
TEST_S(rm->rm_encoding, "telephone-event");
|
|
TEST_1(!rm->rm_next);
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* Re-O/A: prune down to single codec. */
|
|
|
|
TEST_1(soa_set_params(a,
|
|
SOATAG_USER_SDP_STR(
|
|
"v=0\r\n"
|
|
"o=left 219498671 2 IN IP4 127.0.0.2\r\n"
|
|
"c=IN IP4 127.0.0.2\r\n"
|
|
"m=audio 5008 RTP/AVP 0 8 97 96 127\r\n"
|
|
"a=rtpmap:96 G729/8000\n"
|
|
"a=rtpmap:97 GSM/8000\n"
|
|
"a=rtpmap:127 CN/8000\n"
|
|
),
|
|
SOATAG_RTP_MISMATCH(0),
|
|
SOATAG_RTP_SELECT(SOA_RTP_SELECT_COMMON),
|
|
TAG_END()));
|
|
TEST_1(soa_set_params(b,
|
|
SOATAG_RTP_MISMATCH(0),
|
|
SOATAG_RTP_SORT(SOA_RTP_SORT_LOCAL),
|
|
SOATAG_RTP_SELECT(SOA_RTP_SELECT_SINGLE),
|
|
TAG_END()));
|
|
|
|
n = soa_generate_offer(a, 1, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(a, &a_sdp, &offer, &offerlen); TEST(n, 1);
|
|
TEST_1(offer != NULL && offer != NONE);
|
|
n = soa_set_remote_sdp(b, 0, offer, offerlen); TEST(n, 1);
|
|
n = soa_generate_answer(b, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(b, &b_sdp, &answer, &answerlen); TEST(n, 1);
|
|
TEST_1(answer != NULL && answer != NONE);
|
|
n = soa_set_remote_sdp(a, 0, answer, -1); TEST(n, 1);
|
|
n = soa_process_answer(a, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(a, &a_sdp, &offer, &offerlen); TEST(n, 1);
|
|
|
|
TEST_1(soa_is_complete(b));
|
|
TEST(soa_activate(b, NULL), 0);
|
|
|
|
TEST_1(soa_is_complete(a));
|
|
TEST(soa_activate(a, NULL), 0);
|
|
|
|
TEST(soa_is_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_remote_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
|
|
TEST_1(m = a_sdp->sdp_media); TEST_1(!m->m_rejected);
|
|
TEST_1(rm = m->m_rtpmaps); TEST(rm->rm_pt, 97);
|
|
TEST_S(rm->rm_encoding, "GSM");
|
|
TEST_1(rm = rm->rm_next); TEST(rm->rm_pt, 127);
|
|
TEST_S(rm->rm_encoding, "CN");
|
|
TEST_1(!rm->rm_next);
|
|
|
|
/* Answering end matches payload types
|
|
then sorts by local preference,
|
|
then select best codec => GSM with pt 97 */
|
|
TEST_1(m = b_sdp->sdp_media); TEST_1(!m->m_rejected);
|
|
TEST_1(rm = m->m_rtpmaps); TEST(rm->rm_pt, 97);
|
|
TEST_S(rm->rm_encoding, "GSM");
|
|
TEST_1(rm = rm->rm_next); TEST(rm->rm_pt, 111);
|
|
TEST_S(rm->rm_encoding, "telephone-event");
|
|
TEST_1(!rm->rm_next);
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* Re-O/A: A generates new SDP offer with single codec only */
|
|
n = soa_generate_offer(a, 1, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(a, &a_sdp, &offer, &offerlen); TEST(n, 1);
|
|
TEST_1(offer != NULL && offer != NONE);
|
|
TEST_1(m = a_sdp->sdp_media); TEST_1(!m->m_rejected);
|
|
TEST_1(rm = m->m_rtpmaps); TEST(rm->rm_pt, 97);
|
|
TEST_S(rm->rm_encoding, "GSM");
|
|
TEST_1(rm = rm->rm_next); TEST(rm->rm_pt, 127);
|
|
TEST_S(rm->rm_encoding, "CN");
|
|
TEST_1(!rm->rm_next);
|
|
n = soa_set_remote_sdp(b, 0, offer, offerlen); TEST(n, 1);
|
|
/* Answer from B is identical to previous one */
|
|
n = soa_generate_answer(b, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(b, &b_sdp, &answer, &answerlen); TEST(n, 1);
|
|
TEST_1(answer != NULL && answer != NONE);
|
|
n = soa_set_remote_sdp(a, 0, answer, -1); TEST(n, 0);
|
|
n = soa_process_answer(a, test_completed); TEST(n, 0);
|
|
|
|
TEST_1(soa_is_complete(b));
|
|
TEST(soa_activate(b, NULL), 0);
|
|
|
|
TEST_1(soa_is_complete(a));
|
|
TEST(soa_activate(a, NULL), 0);
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
/* Add new media - without common codecs */
|
|
TEST_1(soa_set_params(a,
|
|
SOATAG_RTP_MISMATCH(0),
|
|
SOATAG_USER_SDP_STR(
|
|
"v=0\r\n"
|
|
"o=left 219498671 2 IN IP4 127.0.0.2\r\n"
|
|
"c=IN IP4 127.0.0.2\r\n"
|
|
"m=audio 5008 RTP/AVP 0 8 96 3 127\r\n"
|
|
"a=rtpmap:96 G729/8000\n"
|
|
"a=rtpmap:127 CN/8000\n"
|
|
"m=video 5010 RTP/AVP 31\r\n"
|
|
"m=audio 6008 RTP/SAVP 3\n"
|
|
),
|
|
TAG_END()));
|
|
TEST_1(soa_set_params(b,
|
|
SOATAG_RTP_MISMATCH(0),
|
|
SOATAG_USER_SDP_STR(
|
|
"v=0\r\n"
|
|
"o=left 219498671 2 IN IP4 127.0.0.2\r\n"
|
|
"c=IN IP4 127.0.0.2\r\n"
|
|
"m=audio 5004 RTP/AVP 96 3 97 111\r\n"
|
|
"a=rtpmap:96 G7231/8000\n"
|
|
"a=rtpmap:97 G729/8000\n"
|
|
"a=rtpmap:111 telephone-event/8000\n"
|
|
"a=fmtp:111 0-15\n"
|
|
"m=audio 6004 RTP/SAVP 96\n"
|
|
"a=rtpmap:96 G729/8000\n"
|
|
"m=video 5006 RTP/AVP 34\n"
|
|
),
|
|
TAG_END()));
|
|
|
|
n = soa_generate_offer(a, 1, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(a, &a_sdp, &offer, &offerlen); TEST(n, 1);
|
|
TEST_1(offer != NULL && offer != NONE);
|
|
TEST_1(m = a_sdp->sdp_media); TEST_1(!m->m_rejected);
|
|
TEST_1(m = m->m_next); TEST_1(!m->m_rejected);
|
|
TEST_1(m = m->m_next); TEST_1(!m->m_rejected);
|
|
TEST_1(!m->m_next);
|
|
n = soa_set_remote_sdp(b, 0, offer, offerlen); TEST(n, 1);
|
|
n = soa_generate_answer(b, test_completed); TEST(n, 0);
|
|
/* Answer from B rejects video */
|
|
n = soa_get_local_sdp(b, &b_sdp, &answer, &answerlen); TEST(n, 1);
|
|
TEST_1(answer != NULL && answer != NONE);
|
|
n = soa_set_remote_sdp(a, 0, answer, -1); TEST(n, 1);
|
|
n = soa_process_answer(a, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(a, &a_sdp, &offer, &offerlen); TEST(n, 1);
|
|
|
|
TEST_1(soa_is_complete(b));
|
|
TEST(soa_activate(b, NULL), 0);
|
|
|
|
TEST_1(soa_is_complete(a));
|
|
TEST(soa_activate(a, NULL), 0);
|
|
|
|
TEST(soa_is_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_remote_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_video_active(a), SOA_ACTIVE_REJECTED);
|
|
TEST(soa_is_remote_video_active(a), SOA_ACTIVE_REJECTED);
|
|
|
|
TEST_1(m = a_sdp->sdp_media); TEST_1(!m->m_rejected);
|
|
TEST_1(m = m->m_next); TEST_1(m->m_rejected);
|
|
TEST_1(m = m->m_next); TEST_1(m->m_rejected);
|
|
TEST_1(!m->m_next);
|
|
|
|
TEST_1(m = b_sdp->sdp_media); TEST_1(!m->m_rejected);
|
|
TEST_1(m = m->m_next); TEST_1(m->m_rejected);
|
|
/* Rejected but tell what we support */
|
|
TEST_1(rm = m->m_rtpmaps); TEST(rm->rm_pt, 34);
|
|
TEST_S(rm->rm_encoding, "H263");
|
|
TEST_1(m = m->m_next); TEST_1(m->m_rejected);
|
|
TEST_1(!m->m_next);
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* A adds H.263 to video */
|
|
TEST_1(soa_set_params(a,
|
|
SOATAG_USER_SDP_STR(
|
|
"v=0\r\n"
|
|
"o=left 219498671 2 IN IP4 127.0.0.2\r\n"
|
|
"c=IN IP4 127.0.0.2\r\n"
|
|
"m=audio 5008 RTP/AVP 0 8 96 3 127\r\n"
|
|
"a=rtpmap:96 G729/8000\n"
|
|
"a=rtpmap:127 CN/8000\n"
|
|
"m=video 5010 RTP/AVP 31 34\r\n"
|
|
"m=audio 6008 RTP/SAVP 3\n"
|
|
),
|
|
TAG_END()));
|
|
|
|
/* B adds GSM to SRTP */
|
|
TEST_1(soa_set_params(b,
|
|
SOATAG_USER_SDP_STR(
|
|
"v=0\r\n"
|
|
"o=left 219498671 2 IN IP4 127.0.0.2\r\n"
|
|
"c=IN IP4 127.0.0.2\r\n"
|
|
"m=audio 5004 RTP/AVP 96 3 97 111\r\n"
|
|
"a=rtpmap:96 G7231/8000\n"
|
|
"a=rtpmap:97 G729/8000\n"
|
|
"a=rtpmap:111 telephone-event/8000\n"
|
|
"a=fmtp:111 0-15\n"
|
|
"m=audio 6004 RTP/SAVP 96 3\n"
|
|
"a=rtpmap:96 G729/8000\n"
|
|
"m=video 5006 RTP/AVP 34\n"
|
|
),
|
|
TAG_END()));
|
|
|
|
n = soa_generate_offer(a, 1, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(a, &a_sdp, &offer, &offerlen); TEST(n, 1);
|
|
TEST_1(offer != NULL && offer != NONE);
|
|
TEST_1(m = a_sdp->sdp_media); TEST_1(!m->m_rejected);
|
|
TEST_1(m = m->m_next); TEST_1(!m->m_rejected);
|
|
TEST_1(m = m->m_next); TEST_1(!m->m_rejected);
|
|
TEST_1(!m->m_next);
|
|
n = soa_set_remote_sdp(b, 0, offer, offerlen); TEST(n, 1);
|
|
n = soa_generate_answer(b, test_completed); TEST(n, 0);
|
|
/* Answer from B now accepts video */
|
|
n = soa_get_local_sdp(b, &b_sdp, &answer, &answerlen); TEST(n, 1);
|
|
TEST_1(answer != NULL && answer != NONE);
|
|
n = soa_set_remote_sdp(a, 0, answer, -1); TEST(n, 1);
|
|
n = soa_process_answer(a, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(a, &a_sdp, &offer, &offerlen); TEST(n, 1);
|
|
|
|
TEST_1(soa_is_complete(b));
|
|
TEST(soa_activate(b, NULL), 0);
|
|
|
|
TEST_1(soa_is_complete(a));
|
|
TEST(soa_activate(a, NULL), 0);
|
|
|
|
TEST(soa_is_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_remote_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_video_active(a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_remote_video_active(a), SOA_ACTIVE_SENDRECV);
|
|
|
|
TEST_1(m = a_sdp->sdp_media); TEST_1(!m->m_rejected);
|
|
TEST_1(m = m->m_next); TEST_1(!m->m_rejected);
|
|
TEST_1(rm = m->m_rtpmaps); TEST(rm->rm_pt, 34);
|
|
TEST_S(rm->rm_encoding, "H263");
|
|
TEST_1(m = m->m_next); TEST_1(!m->m_rejected);
|
|
TEST_1(!m->m_next);
|
|
|
|
TEST_1(m = b_sdp->sdp_media); TEST_1(!m->m_rejected);
|
|
TEST_1(m = m->m_next); TEST_1(!m->m_rejected);
|
|
TEST_1(rm = m->m_rtpmaps); TEST(rm->rm_pt, 34);
|
|
TEST_S(rm->rm_encoding, "H263");
|
|
TEST_1(m = m->m_next); TEST_1(!m->m_rejected);
|
|
TEST_1(!m->m_next);
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/* A drops GSM support */
|
|
|
|
TEST_1(soa_set_params(a,
|
|
SOATAG_USER_SDP_STR(
|
|
"v=0\r\n"
|
|
"o=left 219498671 2 IN IP4 127.0.0.2\r\n"
|
|
"c=IN IP4 127.0.0.2\r\n"
|
|
"m=audio 5008 RTP/AVP 0 8 96 127\r\n"
|
|
"a=rtpmap:96 G729/8000\n"
|
|
"a=rtpmap:127 CN/8000\n"
|
|
"m=video 5010 RTP/AVP 31 34\r\n"
|
|
"m=audio 6008 RTP/SAVP 3\n"
|
|
),
|
|
TAG_END()));
|
|
|
|
/* B adds GSM to SRTP, changes IP address */
|
|
TEST_1(soa_set_params(b,
|
|
SOATAG_USER_SDP_STR(
|
|
"v=0\r\n"
|
|
"o=left 219498671 2 IN IP4 127.0.0.2\r\n"
|
|
"c=IN IP4 127.0.0.3\r\n"
|
|
"m=audio 5004 RTP/AVP 96 3 97 111\r\n"
|
|
"a=rtpmap:96 G7231/8000\n"
|
|
"a=rtpmap:97 G729/8000\n"
|
|
"a=rtpmap:111 telephone-event/8000\n"
|
|
"a=fmtp:111 0-15\n"
|
|
"m=audio 6004 RTP/SAVP 96 3\n"
|
|
"a=rtpmap:96 G729/8000\n"
|
|
"m=video 5006 RTP/AVP 34\n"
|
|
),
|
|
TAG_END()));
|
|
|
|
n = soa_generate_offer(a, 1, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(a, &a_sdp, &offer, &offerlen); TEST(n, 1);
|
|
TEST_1(offer != NULL && offer != NONE);
|
|
TEST_1(m = a_sdp->sdp_media); TEST_1(!m->m_rejected);
|
|
TEST_1(m = m->m_next); TEST_1(!m->m_rejected);
|
|
TEST_1(m = m->m_next); TEST_1(!m->m_rejected);
|
|
TEST_1(!m->m_next);
|
|
n = soa_set_remote_sdp(b, 0, offer, offerlen); TEST(n, 1);
|
|
n = soa_generate_answer(b, test_completed); TEST(n, 0);
|
|
/* Answer from B now accepts video */
|
|
n = soa_get_local_sdp(b, &b_sdp, &answer, &answerlen); TEST(n, 1);
|
|
TEST_1(answer != NULL && answer != NONE);
|
|
/* Check that updated c= line is propagated */
|
|
TEST_1(b_sdp->sdp_connection);
|
|
TEST_S(b_sdp->sdp_connection->c_address, "127.0.0.3");
|
|
n = soa_set_remote_sdp(a, 0, answer, -1); TEST(n, 1);
|
|
n = soa_process_answer(a, test_completed); TEST(n, 0);
|
|
n = soa_get_local_sdp(a, &a_sdp, &offer, &offerlen); TEST(n, 1);
|
|
|
|
TEST_1(soa_is_complete(b));
|
|
TEST(soa_activate(b, NULL), 0);
|
|
|
|
TEST_1(soa_is_complete(a));
|
|
TEST(soa_activate(a, NULL), 0);
|
|
|
|
TEST(soa_is_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_remote_audio_active(a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_video_active(a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_remote_video_active(a), SOA_ACTIVE_SENDRECV);
|
|
|
|
TEST_1(m = a_sdp->sdp_media); TEST_1(!m->m_rejected);
|
|
TEST_1(rm = m->m_rtpmaps); TEST(rm->rm_pt, 96);
|
|
TEST_S(rm->rm_encoding, "G729");
|
|
TEST_1(rm = rm->rm_next); TEST(rm->rm_pt, 127);
|
|
TEST_S(rm->rm_encoding, "CN");
|
|
TEST_1(m = m->m_next); TEST_1(!m->m_rejected);
|
|
TEST_1(rm = m->m_rtpmaps); TEST(rm->rm_pt, 34);
|
|
TEST_S(rm->rm_encoding, "H263");
|
|
TEST_1(m = m->m_next); TEST_1(!m->m_rejected);
|
|
TEST_1(!m->m_next);
|
|
|
|
TEST_1(m = b_sdp->sdp_media); TEST_1(!m->m_rejected);
|
|
TEST_1(rm = m->m_rtpmaps); TEST(rm->rm_pt, 96);
|
|
TEST_S(rm->rm_encoding, "G729");
|
|
TEST_1(rm = rm->rm_next); TEST(rm->rm_pt, 111);
|
|
TEST_S(rm->rm_encoding, "telephone-event");
|
|
TEST_1(m = m->m_next); TEST_1(!m->m_rejected);
|
|
TEST_1(rm = m->m_rtpmaps); TEST(rm->rm_pt, 34);
|
|
TEST_S(rm->rm_encoding, "H263");
|
|
TEST_1(m = m->m_next); TEST_1(!m->m_rejected);
|
|
TEST_1(!m->m_next);
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
TEST_VOID(soa_terminate(a, NULL));
|
|
TEST_VOID(soa_terminate(b, NULL));
|
|
|
|
TEST_VOID(soa_destroy(a));
|
|
TEST_VOID(soa_destroy(b));
|
|
|
|
END();
|
|
}
|
|
|
|
|
|
int test_asynch_offer_answer(struct context *ctx)
|
|
{
|
|
BEGIN();
|
|
|
|
#if 0
|
|
int n;
|
|
|
|
char const *caps = NONE, *offer = NONE, *answer = NONE;
|
|
isize_t capslen = -1, offerlen = -1, answerlen = -1;
|
|
|
|
char const a[] =
|
|
"v=0\r\n"
|
|
"o=left 219498671 2 IN IP4 127.0.0.2\r\n"
|
|
"c=IN IP4 127.0.0.2\r\n"
|
|
"m=audio 5004 RTP/AVP 0 8\r\n";
|
|
|
|
char const b[] =
|
|
"v=0\n"
|
|
"o=right 93298573265 321974 IN IP4 127.0.0.3\n"
|
|
"c=IN IP4 127.0.0.3\n"
|
|
"m=audio 5006 RTP/AVP 96\n"
|
|
"m=rtpmap:96 GSM/8000\n";
|
|
|
|
n = soa_set_capability_sdp(ctx->asynch.a, 0,
|
|
"m=audio 5004 RTP/AVP 0 8", -1);
|
|
TEST(n, 1);
|
|
|
|
n = soa_set_capability_sdp(ctx->asynch.a, 0, a, strlen(a)); TEST(n, 1);
|
|
n = soa_get_capability_sdp(ctx->asynch.a, 0, &caps, &capslen); TEST(n, 1);
|
|
|
|
TEST_1(caps != NULL && caps != NONE);
|
|
TEST_1(capslen > 0);
|
|
|
|
n = soa_set_capability_sdp(ctx->asynch.b, 0, b, strlen(b)); TEST(n, 1);
|
|
|
|
n = soa_generate_offer(ctx->asynch.a, 1, test_completed); TEST(n, 1);
|
|
|
|
su_root_run(ctx->root); TEST(ctx->completed, ctx->asynch.a);
|
|
ctx->completed = NULL;
|
|
|
|
n = soa_get_local_sdp(ctx->asynch.a, 0, &offer, &offerlen); TEST(n, 1);
|
|
|
|
n = soa_set_remote_sdp(ctx->asynch.b, 0, offer, offerlen); TEST(n, 1);
|
|
|
|
n = soa_generate_answer(ctx->asynch.b, test_completed); TEST(n, 1);
|
|
|
|
su_root_run(ctx->root); TEST(ctx->completed, ctx->asynch.b);
|
|
ctx->completed = NULL;
|
|
|
|
TEST_1(soa_is_complete(ctx->asynch.b));
|
|
TEST(soa_activate(ctx->asynch.b, NULL), 0);
|
|
|
|
n = soa_get_local_sdp(ctx->asynch.b, 0, &answer, &answerlen); TEST(n, 1);
|
|
|
|
n = soa_set_remote_sdp(ctx->asynch.a, 0, answer, answerlen); TEST(n, 1);
|
|
|
|
n = soa_process_answer(ctx->asynch.a, test_completed); TEST(n, 1);
|
|
|
|
su_root_run(ctx->root); TEST(ctx->completed, ctx->asynch.a);
|
|
ctx->completed = NULL;
|
|
|
|
TEST_1(soa_is_complete(ctx->asynch.a));
|
|
TEST(soa_activate(ctx->asynch.a, NULL), 0);
|
|
|
|
TEST(soa_is_audio_active(ctx->asynch.a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_video_active(ctx->asynch.a), SOA_ACTIVE_DISABLED);
|
|
TEST(soa_is_image_active(ctx->asynch.a), SOA_ACTIVE_DISABLED);
|
|
TEST(soa_is_chat_active(ctx->asynch.a), SOA_ACTIVE_DISABLED);
|
|
|
|
TEST(soa_is_remote_audio_active(ctx->asynch.a), SOA_ACTIVE_SENDRECV);
|
|
TEST(soa_is_remote_video_active(ctx->asynch.a), SOA_ACTIVE_DISABLED);
|
|
TEST(soa_is_remote_image_active(ctx->asynch.a), SOA_ACTIVE_DISABLED);
|
|
TEST(soa_is_remote_chat_active(ctx->asynch.a), SOA_ACTIVE_DISABLED);
|
|
|
|
TEST(soa_deactivate(ctx->asynch.a, NULL), 0);
|
|
TEST(soa_deactivate(ctx->asynch.b, NULL), 0);
|
|
|
|
TEST_VOID(soa_terminate(ctx->asynch.a, NULL));
|
|
|
|
TEST(soa_is_audio_active(ctx->asynch.a), SOA_ACTIVE_DISABLED);
|
|
TEST(soa_is_remote_audio_active(ctx->asynch.a), SOA_ACTIVE_DISABLED);
|
|
|
|
TEST_VOID(soa_terminate(ctx->asynch.b, NULL));
|
|
|
|
#endif
|
|
|
|
END();
|
|
}
|
|
|
|
int test_deinit(struct context *ctx)
|
|
{
|
|
BEGIN();
|
|
END();
|
|
}
|
|
|
|
#if HAVE_ALARM
|
|
static RETSIGTYPE sig_alarm(int s)
|
|
{
|
|
fprintf(stderr, "%s: FAIL! test timeout!\n", name);
|
|
exit(1);
|
|
}
|
|
#endif
|
|
|
|
void usage(void)
|
|
{
|
|
fprintf(stderr,
|
|
"usage: %s [-v|-q] [-l level] [-p outbound-proxy-uri]\n",
|
|
name);
|
|
exit(1);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int retval = 0, quit_on_single_failure = 0;
|
|
int i, o_attach = 0, o_alarm = 1;
|
|
|
|
struct context ctx[1] = {{{ SU_HOME_INIT(ctx) }}};
|
|
|
|
for (i = 1; argv[i]; i++) {
|
|
if (strcmp(argv[i], "-v") == 0)
|
|
tstflags |= tst_verbatim;
|
|
else if (strcmp(argv[i], "-q") == 0)
|
|
tstflags &= ~tst_verbatim;
|
|
else if (strcmp(argv[i], "-1") == 0)
|
|
quit_on_single_failure = 1;
|
|
else if (strncmp(argv[i], "-l", 2) == 0) {
|
|
int level = 3;
|
|
char *rest = NULL;
|
|
|
|
if (argv[i][2])
|
|
level = strtol(argv[i] + 2, &rest, 10);
|
|
else if (argv[i + 1])
|
|
level = strtol(argv[i + 1], &rest, 10), i++;
|
|
else
|
|
level = 3, rest = "";
|
|
|
|
if (rest == NULL || *rest)
|
|
usage();
|
|
|
|
su_log_set_level(soa_log, level);
|
|
}
|
|
else if (strcmp(argv[i], "--attach") == 0) {
|
|
o_attach = 1;
|
|
}
|
|
else if (strcmp(argv[i], "--no-alarm") == 0) {
|
|
o_alarm = 0;
|
|
}
|
|
else if (strcmp(argv[i], "-") == 0) {
|
|
i++; break;
|
|
}
|
|
else if (argv[i][0] != '-') {
|
|
break;
|
|
}
|
|
else
|
|
usage();
|
|
}
|
|
|
|
if (o_attach) {
|
|
char line[10];
|
|
printf("%s: pid %u\n", name, getpid());
|
|
printf("<Press RETURN to continue>\n");
|
|
fgets(line, sizeof line, stdin);
|
|
}
|
|
#if HAVE_ALARM
|
|
else if (o_alarm) {
|
|
alarm(60);
|
|
signal(SIGALRM, sig_alarm);
|
|
}
|
|
#endif
|
|
|
|
su_init();
|
|
|
|
if (!(TSTFLAGS & tst_verbatim)) {
|
|
su_log_soft_set_level(soa_log, 0);
|
|
}
|
|
|
|
#define SINGLE_FAILURE_CHECK() \
|
|
do { fflush(stdout); \
|
|
if (retval && quit_on_single_failure) { su_deinit(); return retval; } \
|
|
} while(0)
|
|
|
|
retval |= test_api_errors(ctx); SINGLE_FAILURE_CHECK();
|
|
retval |= test_soa_tags(ctx); SINGLE_FAILURE_CHECK();
|
|
retval |= test_init(ctx, argv + i); SINGLE_FAILURE_CHECK();
|
|
if (retval == 0) {
|
|
retval |= test_params(ctx); SINGLE_FAILURE_CHECK();
|
|
retval |= test_static_offer_answer(ctx); SINGLE_FAILURE_CHECK();
|
|
retval |= test_codec_selection(ctx); SINGLE_FAILURE_CHECK();
|
|
|
|
retval |= test_asynch_offer_answer(ctx); SINGLE_FAILURE_CHECK();
|
|
}
|
|
retval |= test_deinit(ctx); SINGLE_FAILURE_CHECK();
|
|
|
|
su_deinit();
|
|
|
|
return retval;
|
|
}
|