Commit 66b293e0 authored by Pekka Pessi's avatar Pekka Pessi
Browse files

Updated SOA API to explicitly generate offer/anwer and process answer.

darcs-hash:20050911194920-65a35-d364276508f31a7dad01df9324ca98426a1f2694.gz
parent 142af125
This diff is collapsed.
......@@ -66,37 +66,42 @@ int soa_error_as_sip_response(soa_session_t *soa,
char const *soa_error_as_sip_reason(soa_session_t *soa);
int soa_parse_sdp(soa_session_t *ss,
int live,
char const *sdp,
int len);
int soa_set_capability_sdp(soa_session_t *ss,
char const *str, int len);
void soa_clear_sdp(soa_session_t *ss);
int soa_get_capability_sdp(soa_session_t *ss,
char const **return_sdp,
int *return_len);
int soa_print_sdp(soa_session_t *ss,
int live,
su_home_t *home,
char **sdp,
int *return_len);
int soa_set_remote_sdp(soa_session_t *ss,
char const *str, int len);
int soa_get_remote_sdp(soa_session_t *ss,
char const **return_sdp,
int *return_len);
int soa_set_local_sdp(soa_session_t *ss,
char const *str, int len);
int soa_get_local_sdp(soa_session_t *ss,
char const **return_sdp,
int *return_len);
char const * const * soa_sip_required(soa_session_t const *ss);
char const * const * soa_sip_support(soa_session_t const *ss);
int soa_remote_sip_features(soa_session_t *ss,
int soa_remote_sip_features(soa_session_t *ss,
char const * const * support,
char const * const * required);
char **soa_media_features(soa_session_t *ss, int live, su_home_t *home);
/* Run offer step */
int soa_offer(soa_session_t *, int always, soa_callback_f *completed);
/* Run O/A step */
int soa_offer_answer(soa_session_t *, int always, soa_callback_f *completed);
/* Run answer step */
int soa_answer(soa_session_t *, int always, soa_callback_f *completed);
/* Generate offer */
int soa_generate_offer(soa_session_t *, int always, soa_callback_f *);
/* Process offer, generate answer */
int soa_generate_answer(soa_session_t *, soa_callback_f *);
/* Process answer */
int soa_process_answer(soa_session_t *, soa_callback_f *);
void soa_activate(soa_session_t *, char const *option);
void soa_terminate(soa_session_t *, char const *option);
......
......@@ -70,6 +70,7 @@ struct soa_asynch_completed
{
soa_session_t *completed_session;
unsigned completed_terminated;
int (*completed_call)(soa_session_t *, soa_callback_f *);
};
static int soa_asynch_init(char const *, soa_session_t *, soa_session_t *);
......@@ -81,6 +82,8 @@ static int soa_asynch_generate_offer(soa_session_t *ss,
soa_callback_f *completed);
static int soa_asynch_generate_answer(soa_session_t *ss,
soa_callback_f *completed);
static int soa_asynch_process_answer(soa_session_t *ss,
soa_callback_f *completed);
static void soa_asynch_activate(soa_session_t *ss, char const *option);
static void soa_asynch_terminate(soa_session_t *ss, char const *option);
......@@ -97,9 +100,12 @@ struct soa_session_actions const soa_asynch_actions =
soa_base_sip_required,
soa_base_sip_support,
soa_base_remote_sip_features,
soa_base_config_sdp,
soa_base_set_capability_sdp,
soa_base_set_remote_sdp,
soa_base_set_local_sdp,
soa_asynch_generate_offer,
soa_asynch_generate_answer,
soa_asynch_process_answer,
soa_asynch_activate,
soa_asynch_terminate
};
......@@ -146,9 +152,9 @@ static void soa_asynch_completed(su_root_magic_t *magic,
ss->ss_in_progress = NULL;
/* Update local activity */
if (ss->ss_local)
soa_set_activity(ss, ss->ss_local->sdp_media, 0);
if (arg->completed_call(ss, NULL) < 0)
/* XXX - Process error */;
completed(ss->ss_magic, ss);
}
}
......@@ -159,25 +165,25 @@ static void soa_asynch_completed(su_root_magic_t *magic,
static int soa_asynch_generate_offer(soa_session_t *ss,
soa_callback_f *completed)
{
sdp_session_t *sdp;
sdp_media_t *m;
uint16_t port = 5004;
su_msg_r msg;
if (ss->ss_local == NULL) {
if (ss->ss_caps == NULL)
if (ss->ss_local->ssd_sdp == NULL) {
if (ss->ss_caps->ssd_unparsed == NULL)
return soa_set_status(ss, 500, "No local session available");
}
if (ss->ss_local)
if (ss->ss_local->ssd_sdp)
return 0; /* We are done */
/* Generate a dummy offer based on our capabilities */
ss->ss_local = sdp_session_dup(ss->ss_home, ss->ss_caps);
if (!ss->ss_local) {
return soa_set_status(ss, 500, "Internal error");
}
/* Generate a dummy SDP offer based on our capabilities */
if (soa_set_local_sdp(ss, ss->ss_caps->ssd_unparsed, -1) < 0)
return -1;
sdp = ss->ss_local->ssd_sdp; assert(ss->ss_local->ssd_sdp);
for (m = ss->ss_local->sdp_media; m; m = m->m_next)
for (m = sdp->sdp_media; m; m = m->m_next)
if (m->m_port == 0)
m->m_port = port, port += 2;
......@@ -191,6 +197,7 @@ static int soa_asynch_generate_offer(soa_session_t *ss,
su_msg_data(msg)->completed_session = soa_session_ref(ss);
su_msg_data(msg)->completed_terminated = ss->ss_terminated;
su_msg_data(msg)->completed_call = soa_base_generate_offer;
su_msg_send(msg);
......@@ -202,25 +209,25 @@ static int soa_asynch_generate_offer(soa_session_t *ss,
static int soa_asynch_generate_answer(soa_session_t *ss,
soa_callback_f *completed)
{
sdp_session_t *sdp;
sdp_media_t *m;
uint16_t port = 5004;
su_msg_r msg;
if (ss->ss_local == NULL) {
if (ss->ss_caps == NULL)
if (ss->ss_local->ssd_sdp == NULL) {
if (ss->ss_caps->ssd_unparsed == NULL)
return soa_set_status(ss, 500, "No local session available");
}
if (ss->ss_local)
if (ss->ss_local->ssd_sdp)
return 0; /* We are done */
/* Generate a dummy answer based on our capabilities */
ss->ss_local = sdp_session_dup(ss->ss_home, ss->ss_caps);
if (!ss->ss_local) {
return soa_set_status(ss, 500, "Internal error");
}
/* Generate a dummy SDP offer based on our capabilities */
if (soa_set_local_sdp(ss, ss->ss_caps->ssd_unparsed, -1) < 0)
return -1;
sdp = ss->ss_local->ssd_sdp; assert(ss->ss_local->ssd_sdp);
for (m = ss->ss_local->sdp_media; m; m = m->m_next)
for (m = sdp->sdp_media; m; m = m->m_next)
if (m->m_port == 0)
m->m_port = port, port += 2;
......@@ -234,6 +241,7 @@ static int soa_asynch_generate_answer(soa_session_t *ss,
su_msg_data(msg)->completed_session = soa_session_ref(ss);
su_msg_data(msg)->completed_terminated = ss->ss_terminated;
su_msg_data(msg)->completed_call = soa_base_generate_answer;
su_msg_send(msg);
......@@ -242,6 +250,31 @@ static int soa_asynch_generate_answer(soa_session_t *ss,
return 1; /* Indicate caller of async operation */
}
static int soa_asynch_process_answer(soa_session_t *ss,
soa_callback_f *completed)
{
su_msg_r msg;
/* We pretend to be asynchronous */
if (su_msg_create(msg,
su_root_task(ss->ss_root),
su_root_task(ss->ss_root),
soa_asynch_completed,
sizeof (struct soa_asynch_completed)) == -1)
return soa_set_status(ss, 500, "Internal error");
su_msg_data(msg)->completed_session = soa_session_ref(ss);
su_msg_data(msg)->completed_terminated = ss->ss_terminated;
su_msg_data(msg)->completed_call = soa_base_process_answer;
su_msg_send(msg);
ss->ss_in_progress = completed;
return 1; /* Indicate caller of async operation */
}
static void soa_asynch_activate(soa_session_t *ss, char const *option)
{
soa_base_activate(ss, option);
......@@ -249,8 +282,7 @@ static void soa_asynch_activate(soa_session_t *ss, char const *option)
static void soa_asynch_terminate(soa_session_t *ss, char const *option)
{
if (ss->ss_local)
su_free(ss->ss_home, ss->ss_local), ss->ss_local = NULL;
ss->ss_in_progress = NULL;
soa_description_free(ss, ss->ss_local);
soa_base_terminate(ss, option);
}
......@@ -57,10 +57,16 @@ struct soa_session_actions
int (*soa_remote_sip_features)(soa_session_t *ss,
char const * const * support,
char const * const * required);
int (*soa_config_sdp)(soa_session_t *ss, sdp_session_t *sdp,
char const *sdp_str, int strlen);
int (*soa_set_capability_sdp)(soa_session_t *, sdp_session_t *,
char const *, int);
int (*soa_set_remote_sdp)(soa_session_t *, int new_version,
sdp_session_t *, char const *, int);
int (*soa_set_local_sdp)(soa_session_t *, sdp_session_t *,
char const *, int);
int (*soa_generate_offer)(soa_session_t *ss, soa_callback_f *completed);
int (*soa_generate_answer)(soa_session_t *ss, soa_callback_f *completed);
int (*soa_process_answer)(soa_session_t *ss,
soa_callback_f *completed);
void (*soa_activate_session)(soa_session_t *ss, char const *option);
void (*soa_terminate_session)(soa_session_t *ss, char const *option);
};
......@@ -79,10 +85,20 @@ char const * const * soa_base_sip_support(soa_session_t const *ss);
int soa_base_remote_sip_features(soa_session_t *ss,
char const * const * support,
char const * const * required);
int soa_base_config_sdp(soa_session_t *ss, sdp_session_t *sdp,
char const *sdp0, int sdp0_len);
int soa_base_set_capability_sdp(soa_session_t *ss,
sdp_session_t *sdp,
char const *, int);
int soa_base_set_remote_sdp(soa_session_t *ss,
int new_version,
sdp_session_t *sdp,
char const *, int);
int soa_base_set_local_sdp(soa_session_t *ss,
sdp_session_t *sdp,
char const *, int);
int soa_base_generate_offer(soa_session_t *ss, soa_callback_f *completed);
int soa_base_generate_answer(soa_session_t *ss, soa_callback_f *completed);
int soa_base_process_answer(soa_session_t *ss,
soa_callback_f *completed);
void soa_base_activate(soa_session_t *ss, char const *option);
void soa_base_terminate(soa_session_t *ss, char const *option);
......@@ -90,6 +106,16 @@ int soa_default_generate_offer(soa_session_t *ss,
soa_callback_f *completed);
int soa_default_generate_answer(soa_session_t *ss,
soa_callback_f *completed);
int soa_default_process_answer(soa_session_t *ss,
soa_callback_f *completed);
struct soa_description
{
sdp_session_t *ssd_sdp; /**< Session description */
char const *ssd_unparsed; /**< Original session description as string */
char const *ssd_str; /**< Session description as string */
sdp_printer_t *ssd_printer; /**< SDP printer object */
};
struct soa_session
{
......@@ -108,9 +134,10 @@ struct soa_session
unsigned ss_active:1; /**< Session has been activated */
/* Current Offer-Answer status */
unsigned ss_complete:1; /**< Completed SDP offer-answer */
unsigned ss_unprocessed_remote:1; /**< We have received remote SDP */
unsigned ss_offer_sent:2; /**< We have offered SDP */
unsigned ss_answer_recv:2; /**< We have received SDP answer */
......@@ -129,17 +156,11 @@ struct soa_session
} ss_local_activity[1], ss_remote_activity[1];
/** Capabilities as specified by application */
char const *ss_caps_str0;
char const *ss_caps_str; /**< Session capabilities as string */
sdp_session_t *ss_caps; /**< Session capabilities */
/** Session description specified by application */
char const *ss_local_str0;
char const *ss_local_str; /**< Local session description as string */
sdp_session_t *ss_local; /**< Local session description */
sdp_parser_t *ss_parser; /**< SDP from incoming request */
sdp_session_t *ss_remote; /**< Remote session description */
struct soa_description ss_caps[1];
/** Local session description */
struct soa_description ss_local[1];
/** Remote session description */
struct soa_description ss_remote[1];
/** SIP features required */
char const * const *ss_local_required;
......@@ -184,6 +205,36 @@ struct soa_session
int soa_set_status(soa_session_t *ss, int status, char const *phrase);
void soa_set_activity(soa_session_t *ss, sdp_media_t const *m, int remote);
int soa_set_capability_sdp_str(soa_session_t *ss,
sdp_session_t const *sdp,
char const *str, int len);
int soa_set_remote_sdp_str(soa_session_t *ss,
sdp_session_t const *sdp,
char const *str, int len);
int soa_set_local_sdp_str(soa_session_t *ss,
sdp_session_t const *sdp,
char const *str, int len);
int soa_description_set(soa_session_t *ss,
struct soa_description *ssd,
sdp_session_t *sdp,
char const *sdp_str,
int sdp_len);
void soa_description_free(soa_session_t *, struct soa_description *ssd);
int soa_description_dup(su_home_t *,
struct soa_description *ssd,
struct soa_description const *ssd0);
int soa_print_sdp(soa_session_t *ss,
int live,
su_home_t *home,
char **sdp,
int *return_len);
/* ====================================================================== */
/* Debug log settings */
......
......@@ -75,6 +75,8 @@ static int soa_static_generate_offer(soa_session_t *ss,
soa_callback_f *completed);
static int soa_static_generate_answer(soa_session_t *ss,
soa_callback_f *completed);
static int soa_static_process_answer(soa_session_t *ss,
soa_callback_f *completed);
static void soa_static_activate(soa_session_t *ss, char const *option);
static void soa_static_terminate(soa_session_t *ss, char const *option);
......@@ -91,9 +93,12 @@ struct soa_session_actions const soa_static_actions =
soa_base_sip_required,
soa_base_sip_support,
soa_base_remote_sip_features,
soa_base_config_sdp,
soa_base_set_capability_sdp,
soa_base_set_remote_sdp,
soa_base_set_local_sdp,
soa_static_generate_offer,
soa_static_generate_answer,
soa_static_process_answer,
soa_static_activate,
soa_static_terminate
};
......@@ -131,61 +136,63 @@ static tagi_t *soa_static_get_paramlist(soa_session_t const *ss)
static int soa_static_generate_offer(soa_session_t *ss,
soa_callback_f *completed)
{
sdp_session_t *sdp;
sdp_media_t *m;
uint16_t port = 5004;
su_msg_r msg;
if (ss->ss_local == NULL) {
if (ss->ss_caps == NULL)
if (ss->ss_local->ssd_sdp == NULL) {
if (ss->ss_caps->ssd_unparsed == NULL)
return soa_set_status(ss, 500, "No local session available");
}
if (ss->ss_local)
if (ss->ss_local->ssd_sdp)
return 0; /* We are done */
/* Generate a dummy offer based on our capabilities */
ss->ss_local = sdp_session_dup(ss->ss_home, ss->ss_caps);
if (!ss->ss_local) {
return soa_set_status(ss, 500, "Internal error");
}
/* Generate a dummy SDP offer based on our capabilities */
if (soa_set_local_sdp(ss, ss->ss_caps->ssd_unparsed, -1) < 0)
return -1;
sdp = ss->ss_local->ssd_sdp; assert(ss->ss_local->ssd_sdp);
for (m = ss->ss_local->sdp_media; m; m = m->m_next)
for (m = sdp->sdp_media; m; m = m->m_next)
if (m->m_port == 0)
m->m_port = port, port += 2;
soa_set_activity(ss, ss->ss_local->sdp_media, 0);
return 0;
return soa_base_generate_offer(ss, NULL);
}
static int soa_static_generate_answer(soa_session_t *ss,
soa_callback_f *completed)
{
sdp_session_t *sdp;
sdp_media_t *m;
uint16_t port = 5004;
su_msg_r msg;
if (ss->ss_local == NULL) {
if (ss->ss_caps == NULL)
if (ss->ss_local->ssd_sdp == NULL) {
if (ss->ss_caps->ssd_unparsed == NULL)
return soa_set_status(ss, 500, "No local session available");
}
if (ss->ss_local)
if (ss->ss_local->ssd_sdp)
return 0; /* We are done */
/* Generate a dummy answer based on our capabilities */
ss->ss_local = sdp_session_dup(ss->ss_home, ss->ss_caps);
if (!ss->ss_local) {
return soa_set_status(ss, 500, "Internal error");
}
/* Generate a dummy SDP offer based on our capabilities */
if (soa_set_local_sdp(ss, ss->ss_caps->ssd_unparsed, -1) < 0)
return -1;
sdp = ss->ss_local->ssd_sdp; assert(ss->ss_local->ssd_sdp);
for (m = ss->ss_local->sdp_media; m; m = m->m_next)
for (m = sdp->sdp_media; m; m = m->m_next)
if (m->m_port == 0)
m->m_port = port, port += 2;
soa_set_activity(ss, ss->ss_local->sdp_media, 0);
return soa_base_generate_answer(ss, NULL);
}
return 0;
static int soa_static_process_answer(soa_session_t *ss,
soa_callback_f *completed)
{
return soa_base_process_answer(ss, NULL);
}
static void soa_static_activate(soa_session_t *ss, char const *option)
......@@ -195,7 +202,6 @@ static void soa_static_activate(soa_session_t *ss, char const *option)
static void soa_static_terminate(soa_session_t *ss, char const *option)
{
if (ss->ss_local)
su_free(ss->ss_home, ss->ss_local), ss->ss_local = NULL;
soa_description_free(ss, ss->ss_local);
soa_base_terminate(ss, option);
}
......@@ -114,10 +114,6 @@ int test_api_errors(struct context *ctx)
TEST_1(-1 == soa_parse_sdp(NULL, 0, NULL, 0));
TEST_VOID(soa_clear_sdp(NULL));
TEST_1(-1 == soa_print_sdp(NULL, 0, NULL, NULL, NULL));
TEST_1(!soa_media_features(NULL, 0, NULL));
TEST_1(!soa_sip_required(NULL));
......@@ -125,11 +121,19 @@ int test_api_errors(struct context *ctx)
TEST_1(-1 == soa_remote_sip_features(NULL, &null, &null));
TEST_1(-1 == soa_offer(NULL, 0, test_api_completed));
TEST_1(soa_set_capability_sdp(NULL, NULL, -1) < 0);
TEST_1(soa_set_remote_sdp(NULL, NULL, -1) < 0);
TEST_1(soa_set_local_sdp(NULL, NULL, -1) < 0);
TEST_1(soa_get_capability_sdp(NULL, NULL, NULL) < 0);
TEST_1(soa_get_local_sdp(NULL, NULL, NULL) < 0);
TEST_1(soa_get_remote_sdp(NULL, NULL, NULL) < 0);
TEST_1(-1 == soa_generate_offer(NULL, 0, test_api_completed));
TEST_1(-1 == soa_offer_answer(NULL, 0, test_api_completed));
TEST_1(-1 == soa_generate_answer(NULL, test_api_completed));
TEST_1(-1 == soa_answer(NULL, 0, test_api_completed));
TEST_1(-1 == soa_process_answer(NULL, test_api_completed));
TEST_VOID(soa_activate(NULL, "both"));
TEST_VOID(soa_terminate(NULL, "both"));
......@@ -219,9 +223,7 @@ int test_static_offer_answer(struct context *ctx)
BEGIN();
int n;
su_home_t home[1] = { SU_HOME_INIT(home) };
char *caps = NONE, *offer = NONE, *answer = NONE;
char const *caps = NONE, *offer = NONE, *answer = NONE;
int capslen = -1, offerlen = -1, answerlen = -1;
char const a[] =
......@@ -237,34 +239,38 @@ int test_static_offer_answer(struct context *ctx)
"m=audio 5006 RTP/AVP 96\n"
"m=rtpmap:96 GSM/8000\n";
n = soa_parse_sdp(ctx->synch.a, 0, "m=audio 5004 RTP/AVP 0 8", -1);
n = soa_set_capability_sdp(ctx->synch.a, "m=audio 5004 RTP/AVP 0 8", -1);
TEST(n, 1);
n = soa_parse_sdp(ctx->synch.a, 0, a, strlen(a)); TEST(n, 1);
n = soa_print_sdp(ctx->synch.a, 0, home, &caps, &capslen); TEST(n, 1);
n = soa_set_capability_sdp(ctx->synch.a, a, strlen(a)); TEST(n, 1);
n = soa_get_capability_sdp(ctx->synch.a, &caps, &capslen); TEST(n, 1);
TEST_1(caps != NULL && caps != NONE);
TEST_1(capslen > 0);
su_free(home, caps);
n = soa_set_capability_sdp(ctx->synch.b, b, strlen(b)); TEST(n, 1);
n = soa_get_local_sdp(ctx->synch.a, &offer, &offerlen); TEST(n, 0);
n = soa_parse_sdp(ctx->synch.b, 0, b, strlen(b)); TEST(n, 1);
n = soa_generate_offer(ctx->synch.a, 1, test_completed); TEST(n, 0);
n = soa_offer(ctx->synch.a, 1, test_completed); TEST(n, 0);
n = soa_get_local_sdp(ctx->synch.a, &offer, &offerlen); TEST(n, 1);
TEST_1(offer != NULL && offer != NONE);
n = soa_print_sdp(ctx->synch.a, 1, home, &offer, &offerlen); TEST(n, 1);
n = soa_set_remote_sdp(ctx->synch.b, offer, offerlen); TEST(n, 1);
n = soa_parse_sdp(ctx->synch.b, 1, offer, offerlen); TEST(n, 1);
n = soa_get_local_sdp(ctx->synch.b, &answer, &answerlen); TEST(n, 0);
n = soa_offer_answer(ctx->synch.b, 0, test_completed); TEST(n, 0);
n = soa_generate_answer(ctx->synch.b, test_completed); TEST(n, 0);
TEST_VOID(soa_activate(ctx->synch.b, NULL));
n = soa_print_sdp(ctx->synch.b, 1, home, &answer, &answerlen); TEST(n, 1);
n = soa_get_local_sdp(ctx->synch.b, &answer, &answerlen); TEST(n, 1);
TEST_1(answer != NULL && answer != NONE);
n = soa_parse_sdp(ctx->synch.a, 1, answer, answerlen); TEST(n, 1);
n = soa_set_remote_sdp(ctx->synch.a, answer, -1); TEST(n, 1);
n = soa_offer_answer(ctx->synch.a, 0, test_completed); TEST(n, 0);
n = soa_process_answer(ctx->synch.a, test_completed); TEST(n, 0);
TEST_VOID(soa_activate(ctx->synch.a, NULL));
......@@ -278,8 +284,6 @@ int test_static_offer_answer(struct context *ctx)
TEST_1(SOA_ACTIVE_DISABLED == soa_is_remote_image_active(ctx->synch.a));
TEST_1(SOA_ACTIVE_DISABLED == soa_is_remote_chat_active(ctx->synch.a));
su_home_deinit(home);
TEST_VOID(soa_terminate(ctx->synch.a, NULL));
TEST_1(SOA_ACTIVE_DISABLED == soa_is_audio_active(ctx->synch.a));
......@@ -296,9 +300,7 @@ int test_asynch_offer_answer(struct context *ctx)
BEGIN();
int n;
su_home_t home[1] = { SU_HOME_INIT(home) };
char *caps = NONE, *offer = NONE, *answer = NONE;
char const *caps = NONE, *offer = NONE, *answer = NONE;
int capslen = -1, offerlen = -1, answerlen = -1;