TFLAG_VOICE = (1 << 6),
TFLAG_RTP_READY = (1 << 7),
TFLAG_CODEC_READY = (1 << 8),
- TFLAG_INIT = (1 << 9),
+ TFLAG_TRANSPORT = (1 << 9),
+ TFLAG_ANSWER = (1 << 10),
} TFLAGS;
typedef enum {
switch_port_t local_port;
switch_port_t remote_port;
char local_user[17];
+ char local_pass[17];
char *remote_user;
unsigned int cand_id;
unsigned int desc_id;
uint32_t last_read;
char *codec_name;
uint8_t codec_num;
- switch_time_t last_cand;
+ switch_time_t next_desc;
switch_time_t next_cand;
char *stun_ip;
uint16_t stun_port;
}
-static void *SWITCH_THREAD_FUNC negotiate_thread_run(switch_thread *thread, void *obj)
+static int activate_rtp(struct private_object *tech_pvt)
{
- switch_core_session *session = obj;
-
- switch_channel *channel;
- struct private_object *tech_pvt = NULL;
- switch_time_t started;
- switch_time_t now;
- unsigned int elapsed;
-
- tech_pvt = switch_core_session_get_private(session);
- assert(tech_pvt != NULL);
+ switch_channel *channel = switch_core_session_get_channel(tech_pvt->session);
+ const char *err;
- channel = switch_core_session_get_channel(session);
- assert(channel != NULL);
+ if (tech_pvt->rtp_session) {
+ return 0;
+ }
- switch_set_flag(tech_pvt, TFLAG_IO);
+ if (switch_core_codec_init(&tech_pvt->read_codec,
+ tech_pvt->codec_name,
+ 8000,
+ 20,
+ 1,
+ SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
+ NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Can't load codec?\n");
+ switch_channel_hangup(channel);
+ return 1;
+ }
+ tech_pvt->read_frame.rate = tech_pvt->read_codec.implementation->samples_per_second;
+ tech_pvt->read_frame.codec = &tech_pvt->read_codec;
- started = switch_time_now();
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set Read Codec to %s\n", tech_pvt->codec_name);
+ if (switch_core_codec_init(&tech_pvt->write_codec,
+ tech_pvt->codec_name,
+ 8000,
+ 20,
+ 1,
+ SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
+ NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Can't load codec?\n");
+ switch_channel_hangup(channel);
+ return -1;
+ }
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set Write Codec to %s\n", tech_pvt->codec_name);
+
+ switch_core_session_set_read_codec(tech_pvt->session, &tech_pvt->read_codec);
+ switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->write_codec);
+
- if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
- tech_pvt->last_cand = switch_time_now();
- tech_pvt->next_cand = tech_pvt->last_cand;
- } else {
- tech_pvt->next_cand = tech_pvt->last_cand + DL_CAND_WAIT;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SETUP RTP %s:%d -> %s:%d\n", tech_pvt->profile->ip, tech_pvt->local_port, tech_pvt->remote_ip, tech_pvt->remote_port);
+
+ if (!(tech_pvt->rtp_session = switch_rtp_new(tech_pvt->profile->ip,
+ tech_pvt->local_port,
+ tech_pvt->remote_ip,
+ tech_pvt->remote_port,
+ tech_pvt->codec_num,
+ tech_pvt->read_codec.implementation->encoded_bytes_per_frame,
+ tech_pvt->read_codec.implementation->microseconds_per_frame,
+ SWITCH_RTP_FLAG_USE_TIMER,
+ NULL,
+ &err, switch_core_session_get_pool(tech_pvt->session)))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RTP ERROR %s\n", err);
+ switch_channel_hangup(channel);
+ return -1;
}
+ switch_rtp_activate_ice(tech_pvt->rtp_session, tech_pvt->remote_user, tech_pvt->local_user);
+
- while(! (switch_test_flag(tech_pvt, TFLAG_CODEC_READY) && switch_test_flag(tech_pvt, TFLAG_RTP_READY) && switch_test_flag(tech_pvt, TFLAG_INIT))) {
- now = switch_time_now();
- elapsed = (unsigned int)((now - started) / 1000);
+ return 0;
+}
- if (switch_channel_get_state(channel) >= CS_HANGUP || switch_test_flag(tech_pvt, TFLAG_BYE)) {
- return NULL;
- }
-
- if (now >= tech_pvt->next_cand) {
- ldl_payload_t payloads[5];
-
- tech_pvt->next_cand += DL_CAND_WAIT;
- memset(payloads, 0, sizeof(payloads));
- if (!switch_test_flag(tech_pvt, TFLAG_CODEC_READY)) {
- if (!tech_pvt->num_codecs) {
- get_codecs(tech_pvt);
- if (!tech_pvt->num_codecs) {
- switch_channel_hangup(channel);
- switch_set_flag(tech_pvt, TFLAG_BYE);
- switch_clear_flag(tech_pvt, TFLAG_IO);
- return NULL;
- }
- }
+static int do_candidates(struct private_object *tech_pvt, int force)
+{
+ switch_channel *channel = switch_core_session_get_channel(tech_pvt->session);
+ assert(channel != NULL);
+ tech_pvt->next_cand += DL_CAND_WAIT;
- if (tech_pvt->codec_index < 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Don't have my codec yet here's one\n");
- tech_pvt->codec_name = tech_pvt->codecs[0]->iananame;
- tech_pvt->codec_num = tech_pvt->codecs[0]->ianacode;
- tech_pvt->codec_index = 0;
- switch_set_flag(tech_pvt, TFLAG_CODEC_READY);
-
- payloads[0].name = tech_pvt->codecs[0]->iananame;
- payloads[0].id = tech_pvt->codecs[0]->ianacode;
-
- } else {
- payloads[0].name = tech_pvt->codecs[tech_pvt->codec_index]->iananame;
- payloads[0].id = tech_pvt->codecs[tech_pvt->codec_index]->ianacode;
- }
- switch_set_flag(tech_pvt, TFLAG_CODEC_READY);
-
- payloads[0].name = tech_pvt->codecs[0]->iananame;
- payloads[0].id = tech_pvt->codecs[0]->ianacode;
- tech_pvt->desc_id = ldl_session_describe(tech_pvt->dlsession, payloads, 1,
- switch_test_flag(tech_pvt, TFLAG_OUTBOUND) ? LDL_DESCRIPTION_INITIATE : LDL_DESCRIPTION_ACCEPT);
- }
- if (! switch_test_flag(tech_pvt, TFLAG_RTP_READY)) {
+ if (force || !switch_test_flag(tech_pvt, TFLAG_RTP_READY)) {
ldl_candidate_t cand[1];
char *advip = tech_pvt->profile->extip ? tech_pvt->profile->extip : tech_pvt->profile->ip;
char *err;
memset(cand, 0, sizeof(cand));
switch_stun_random_string(tech_pvt->local_user, 16, NULL);
+ switch_stun_random_string(tech_pvt->local_pass, 16, NULL);
cand[0].port = tech_pvt->local_port;
if (!stun_ip) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Stun Failed! NO STUN SERVER!\n");
switch_channel_hangup(channel);
- break;
+ return -1;
}
cand[0].address = tech_pvt->profile->ip;
switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Stun Failed! %s:%d [%s]\n", stun_ip, SWITCH_STUN_DEFAULT_PORT, err);
switch_channel_hangup(channel);
- break;
+ return -1;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Stun Success %s:%d\n", cand[0].address, cand[0].port);
}
cand[0].name = "rtp";
cand[0].username = tech_pvt->local_user;
- cand[0].password = tech_pvt->local_user;
+ cand[0].password = tech_pvt->local_pass;
cand[0].pref = 1;
cand[0].protocol = "udp";
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send Candidate %s:%d [%s]\n", cand[0].address, cand[0].port, cand[0].username);
tech_pvt->cand_id = ldl_session_candidates(tech_pvt->dlsession, cand, 1);
switch_set_flag(tech_pvt, TFLAG_RTP_READY);
}
- }
- if (elapsed > 60000) {
+ return 0;
+}
+
+static int do_describe(struct private_object *tech_pvt, int force)
+{
+ ldl_payload_t payloads[5];
+ switch_channel *channel = switch_core_session_get_channel(tech_pvt->session);
+ assert(channel != NULL);
+
+ tech_pvt->next_desc += DL_CAND_WAIT;
+
+ memset(payloads, 0, sizeof(payloads));
+
+ if (!tech_pvt->num_codecs) {
+ get_codecs(tech_pvt);
+ if (!tech_pvt->num_codecs) {
switch_channel_hangup(channel);
switch_set_flag(tech_pvt, TFLAG_BYE);
switch_clear_flag(tech_pvt, TFLAG_IO);
- return NULL;
+ return -1;
}
- if (switch_test_flag(tech_pvt, TFLAG_BYE) || ! switch_test_flag(tech_pvt, TFLAG_IO)) {
- return NULL;
- }
- switch_yield(1000);
- //printf("WAIT %s %d %d %d\n", switch_channel_get_name(channel), switch_test_flag(tech_pvt, TFLAG_INIT), switch_test_flag(tech_pvt, TFLAG_CODEC_READY), switch_test_flag(tech_pvt, TFLAG_RTP_READY));
}
- if (switch_channel_get_state(channel) >= CS_HANGUP || switch_test_flag(tech_pvt, TFLAG_BYE)) {
- return NULL;
- }
+ if (force || !switch_test_flag(tech_pvt, TFLAG_CODEC_READY)) {
+ if (tech_pvt->codec_index < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Don't have my codec yet here's one\n");
+ tech_pvt->codec_name = tech_pvt->codecs[0]->iananame;
+ tech_pvt->codec_num = tech_pvt->codecs[0]->ianacode;
+ tech_pvt->codec_index = 0;
+
+ payloads[0].name = tech_pvt->codecs[0]->iananame;
+ payloads[0].id = tech_pvt->codecs[0]->ianacode;
+
+ } else {
+ payloads[0].name = tech_pvt->codecs[tech_pvt->codec_index]->iananame;
+ payloads[0].id = tech_pvt->codecs[tech_pvt->codec_index]->ianacode;
+ }
- if (switch_core_codec_init(&tech_pvt->read_codec,
- tech_pvt->codec_name,
- 8000,
- 20,
- 1,
- SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
- NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Can't load codec?\n");
- switch_channel_hangup(channel);
- return NULL;
- }
- tech_pvt->read_frame.rate = tech_pvt->read_codec.implementation->samples_per_second;
- tech_pvt->read_frame.codec = &tech_pvt->read_codec;
+
+ payloads[0].name = tech_pvt->codecs[0]->iananame;
+ payloads[0].id = tech_pvt->codecs[0]->ianacode;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Send Describe [%s]\n", payloads[0].name);
+ tech_pvt->desc_id = ldl_session_describe(tech_pvt->dlsession, payloads, 1,
+ switch_test_flag(tech_pvt, TFLAG_OUTBOUND) ? LDL_DESCRIPTION_INITIATE : LDL_DESCRIPTION_ACCEPT);
+ switch_set_flag(tech_pvt, TFLAG_CODEC_READY);
+ }
+
+ return 0;
+}
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set Read Codec to %s\n", tech_pvt->codec_name);
+static void *SWITCH_THREAD_FUNC negotiate_thread_run(switch_thread *thread, void *obj)
+{
+ switch_core_session *session = obj;
- if (switch_core_codec_init(&tech_pvt->write_codec,
- tech_pvt->codec_name,
- 8000,
- 20,
- 1,
- SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
- NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Can't load codec?\n");
- switch_channel_hangup(channel);
- return NULL;
+ switch_channel *channel;
+ struct private_object *tech_pvt = NULL;
+ switch_time_t started;
+ switch_time_t now;
+ unsigned int elapsed;
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ switch_set_flag(tech_pvt, TFLAG_IO);
+
+ started = switch_time_now();
+
+ if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
+ tech_pvt->next_desc = switch_time_now();
+ } else {
+ tech_pvt->next_cand = switch_time_now() + DL_CAND_WAIT;
+ tech_pvt->next_desc = switch_time_now() + DL_CAND_WAIT;
}
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set Write Codec to %s\n", tech_pvt->codec_name);
-
- switch_core_session_set_read_codec(session, &tech_pvt->read_codec);
- switch_core_session_set_write_codec(session, &tech_pvt->write_codec);
- if (!tech_pvt->rtp_session) {
- const char *err;
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SETUP RTP %s:%d -> %s:%d\n", tech_pvt->profile->ip, tech_pvt->local_port, tech_pvt->remote_ip, tech_pvt->remote_port);
-
- if (!(tech_pvt->rtp_session = switch_rtp_new(tech_pvt->profile->ip,
- tech_pvt->local_port,
- tech_pvt->remote_ip,
- tech_pvt->remote_port,
- tech_pvt->codec_num,
- tech_pvt->read_codec.implementation->encoded_bytes_per_frame,
- tech_pvt->read_codec.implementation->microseconds_per_frame,
- SWITCH_RTP_FLAG_USE_TIMER,
- NULL,
- &err, switch_core_session_get_pool(tech_pvt->session)))) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RTP ERROR %s\n", err);
+ while(! (switch_test_flag(tech_pvt, TFLAG_CODEC_READY) &&
+ switch_test_flag(tech_pvt, TFLAG_RTP_READY) &&
+ switch_test_flag(tech_pvt, TFLAG_ANSWER) &&
+ switch_test_flag(tech_pvt, TFLAG_TRANSPORT))) {
+ now = switch_time_now();
+ elapsed = (unsigned int)((now - started) / 1000);
+
+ if (switch_channel_get_state(channel) >= CS_HANGUP || switch_test_flag(tech_pvt, TFLAG_BYE)) {
+ return NULL;
+ }
+
+
+ if (now >= tech_pvt->next_desc) {
+ if (do_describe(tech_pvt, 0) < 0) {
+ break;
+ }
+ }
+
+ if (tech_pvt->next_cand && now >= tech_pvt->next_cand) {
+ if (do_candidates(tech_pvt, 0) < 0) {
+ break;
+ }
+ }
+ if (elapsed > 60000) {
switch_channel_hangup(channel);
+ switch_set_flag(tech_pvt, TFLAG_BYE);
+ switch_clear_flag(tech_pvt, TFLAG_IO);
+ return NULL;
+ }
+ if (switch_test_flag(tech_pvt, TFLAG_BYE) || ! switch_test_flag(tech_pvt, TFLAG_IO)) {
return NULL;
}
- switch_rtp_activate_ice(tech_pvt->rtp_session, tech_pvt->remote_user, tech_pvt->local_user);
+ switch_yield(1000);
+ //printf("WAIT %s %d %d %d %d\n", switch_channel_get_name(channel), switch_test_flag(tech_pvt, TFLAG_TRANSPORT), switch_test_flag(tech_pvt, TFLAG_CODEC_READY), switch_test_flag(tech_pvt, TFLAG_RTP_READY), switch_test_flag(tech_pvt, TFLAG_ANSWER));
}
+
+ if (switch_channel_get_state(channel) >= CS_HANGUP || switch_test_flag(tech_pvt, TFLAG_BYE)) {
+ return NULL;
+ }
-
- //printf("WAIT %s %d\n", switch_channel_get_name(channel), switch_test_flag(tech_pvt, TFLAG_OUTBOUND));
-
+ activate_rtp(tech_pvt);
+
if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
+ do_candidates(tech_pvt, 0);
switch_channel_answer(channel);
//printf("***************************ANSWER\n");
} else {
ldl_session_set_private(dlsession, *new_session);
tech_pvt->dlsession = dlsession;
get_codecs(tech_pvt);
- tech_pvt->desc_id = ldl_session_describe(dlsession, NULL, 0, LDL_DESCRIPTION_INITIATE);
+ //tech_pvt->desc_id = ldl_session_describe(dlsession, NULL, 0, LDL_DESCRIPTION_INITIATE);
negotiate_thread_launch(*new_session);
return SWITCH_STATUS_SUCCESS;
tech_pvt->codec_index = -1;
tech_pvt->profile = profile;
tech_pvt->local_port = switch_rtp_request_port();
+ switch_set_flag(tech_pvt, TFLAG_ANSWER);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Hey where is my memory pool?\n");
switch_core_session_destroy(&session);
ldl_payload_t *payloads;
unsigned int len = 0;
+ if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
+ if (!strcasecmp(msg, "accept")) {
+ switch_set_flag(tech_pvt, TFLAG_ANSWER);
+ do_candidates(tech_pvt, 0);
+ }
+ }
if (tech_pvt->codec_index > -1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Already decided on a codec\n");
}
}
+
if (ldl_session_get_payloads(dlsession, &payloads, &len) == LDL_STATUS_SUCCESS) {
unsigned int x, y;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%u payloads\n", len);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Choosing Payload index %u %s %u\n", y, payloads[x].name, payloads[x].id);
tech_pvt->codec_name = tech_pvt->codecs[y]->iananame;
tech_pvt->codec_num = tech_pvt->codecs[y]->ianacode;
- switch_set_flag(tech_pvt, TFLAG_CODEC_READY);
+ if (!switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
+ do_describe(tech_pvt, 0);
+ }
return LDL_STATUS_SUCCESS;
}
}
}
}
}
+
+
break;
case LDL_SIGNAL_CANDIDATES:
if (signal) {
memset(payloads, 0, sizeof(payloads));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Acceptable Candidate %s:%d\n", candidates[x].address, candidates[x].port);
-
if (!tech_pvt->num_codecs) {
get_codecs(tech_pvt);
ldl_session_set_ip(dlsession, tech_pvt->remote_ip);
tech_pvt->remote_port = candidates[x].port;
tech_pvt->remote_user = switch_core_session_strdup(session, candidates[x].username);
- switch_set_flag(tech_pvt, TFLAG_INIT);
- tech_pvt->next_cand = switch_time_now();
+ if (!switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
+ do_candidates(tech_pvt, 0);
+ }
+ switch_set_flag(tech_pvt, TFLAG_TRANSPORT);
+
return LDL_STATUS_SUCCESS;
}
}