diff --git a/freeswitch.spec b/freeswitch.spec index ce83e83f75..eaf34fc89e 100644 --- a/freeswitch.spec +++ b/freeswitch.spec @@ -320,7 +320,7 @@ export QA_RPATHS=$[ 0x0001|0x0002 ] # Application Modules # ############################################################################################################################### -APPLICATION_MODULES_AE="applications/mod_avmd applications/mod_commands applications/mod_conference applications/mod_db applications/mod_directory applications/mod_distributor applications/mod_dptools applications/mod_easyroute applications/mod_enum applications/mod_esf applications/mod_expr" +APPLICATION_MODULES_AE="applications/mod_avmd applications/mod_commands applications/mod_conference applications/mod_db applications/mod_directory applications/mod_distributor applications/mod_dptools applications/mod_easyroute applications/mod_enum applications/mod_esf applications/mod_expr applications/mod_callcenter" APPLICATION_MODULES_FM="applications/mod_fifo applications/mod_fsv applications/mod_hash applications/mod_lcr applications/mod_limit applications/mod_memcache" @@ -595,6 +595,7 @@ fi %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/mime.types %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/acl.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/alsa.conf.xml +%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/callcenter.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/cdr_csv.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/cdr_pg_csv.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/cidlookup.conf.xml @@ -741,6 +742,7 @@ fi %{prefix}/mod/mod_event_multicast.so* %{prefix}/mod/mod_event_socket.so* %{prefix}/mod/mod_expr.so* +%{prefix}/mod/mod_callcenter.so* %{prefix}/mod/mod_fifo.so* %{prefix}/mod/mod_file_string.so* %{prefix}/mod/mod_flite.so* diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index afdde55757..9914796597 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2261,11 +2261,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_close(ftdm_channel_t **ftdmchan) return FTDM_FAIL; } - if (!ftdm_test_flag(check, FTDM_CHANNEL_INUSE)) { - ftdm_log(FTDM_LOG_WARNING, "Called ftdm_channel_close but never ftdm_channel_open in chan %d:%d??\n", check->span_id, check->chan_id); - return FTDM_FAIL; - } - if (ftdm_test_flag(check, FTDM_CHANNEL_CONFIGURED)) { ftdm_mutex_lock(check->mutex); if (ftdm_test_flag(check, FTDM_CHANNEL_OPEN)) { @@ -2275,6 +2270,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_close(ftdm_channel_t **ftdmchan) ftdm_channel_reset(check); *ftdmchan = NULL; } + } else { + ftdm_log_chan_msg(check, FTDM_LOG_WARNING, "Called ftdm_channel_close but never ftdm_channel_open??\n"); } check->ring_count = 0; ftdm_mutex_unlock(check->mutex); diff --git a/src/mod/applications/mod_nibblebill/mod_nibblebill.c b/src/mod/applications/mod_nibblebill/mod_nibblebill.c index 58ebd146f8..06bc7d0abd 100755 --- a/src/mod/applications/mod_nibblebill/mod_nibblebill.c +++ b/src/mod/applications/mod_nibblebill/mod_nibblebill.c @@ -483,8 +483,6 @@ static switch_status_t do_billing(switch_core_session_t *session) /* Setup new billing data (based on call answer time, in case this module started late with active calls) */ nibble_data->lastts = profile->times->answered; /* Set the initial answer time to match when the call was really answered */ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Beginning new billing on %s\n", uuid); - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Last successful billing time was %s\n", date); } switch_time_exp_lt(&tm, nibble_data->lastts); diff --git a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c index 01cb10edb2..add0dbc865 100644 --- a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c +++ b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c @@ -126,6 +126,9 @@ struct codec_data { long lastrxseqno; unsigned long rxlost; + /* discarded silence packets */ + unsigned long rxdiscarded; + /* avg Rx time */ switch_time_t avgrxus; switch_time_t last_rx_time; @@ -400,26 +403,31 @@ static switch_status_t switch_sangoma_encode(switch_codec_t *codec, switch_codec sess->encoder.tx++; /* do the reading */ - memset(&encoded_frame, 0, sizeof(encoded_frame)); - sres = switch_rtp_zerocopy_read_frame(sess->encoder.rxrtp, &encoded_frame, SWITCH_IO_FLAG_NOBLOCK); - if (sres == SWITCH_STATUS_GENERR) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read on Sangoma encoder RTP session: %d\n", sres); - return SWITCH_STATUS_FALSE; - } + for ( ; ; ) { + sres = switch_rtp_zerocopy_read_frame(sess->encoder.rxrtp, &encoded_frame, SWITCH_IO_FLAG_NOBLOCK); + if (sres == SWITCH_STATUS_GENERR) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read on Sangoma encoder RTP session: %d\n", sres); + return SWITCH_STATUS_FALSE; + } - if (0 == encoded_frame.datalen) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No output on Sangoma encoder RTP session.\n"); - return SWITCH_STATUS_SUCCESS; - } + if (0 == encoded_frame.datalen) { + break; + } - if (encoded_frame.payload != codec->implementation->ianacode - && encoded_frame.payload != IANACODE_CN) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read unexpected payload %d in Sangoma encoder RTP session, expecting %d\n", - encoded_frame.payload, codec->implementation->ianacode); - return SWITCH_STATUS_FALSE; + if (encoded_frame.payload != codec->implementation->ianacode + && encoded_frame.payload != IANACODE_CN) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read unexpected payload %d in Sangoma encoder RTP session, expecting %d\n", + encoded_frame.payload, codec->implementation->ianacode); + break; + } + + if (*encoded_data_len) { + sess->encoder.rxdiscarded++; + } + + memcpy(encoded_data, encoded_frame.data, encoded_frame.datalen); + *encoded_data_len = encoded_frame.datalen; } - memcpy(encoded_data, encoded_frame.data, encoded_frame.datalen); - *encoded_data_len = encoded_frame.datalen; /* update encoding stats */ sess->encoder.rx++; @@ -513,30 +521,34 @@ static switch_status_t switch_sangoma_decode(switch_codec_t *codec, /* codec ses sess->decoder.tx++; /* do the reading */ - memset(&ulaw_frame, 0, sizeof(ulaw_frame)); - sres = switch_rtp_zerocopy_read_frame(sess->decoder.rxrtp, &ulaw_frame, SWITCH_IO_FLAG_NOBLOCK); - if (sres == SWITCH_STATUS_GENERR) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read on Sangoma decoder RTP session: %d\n", sres); - return SWITCH_STATUS_FALSE; - } + for ( ; ; ) { + sres = switch_rtp_zerocopy_read_frame(sess->decoder.rxrtp, &ulaw_frame, SWITCH_IO_FLAG_NOBLOCK); + if (sres == SWITCH_STATUS_GENERR) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read on Sangoma decoder RTP session: %d\n", sres); + return SWITCH_STATUS_FALSE; + } - if (0 == ulaw_frame.datalen) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No output on Sangoma decoder RTP session.\n"); - return SWITCH_STATUS_SUCCESS; - } + if (0 == ulaw_frame.datalen) { + break; + } - if (ulaw_frame.payload != IANA_ULAW - && ulaw_frame.payload != IANACODE_CN) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read unexpected payload %d in Sangoma decoder RTP session, expecting %d\n", - ulaw_frame.payload, IANA_ULAW); - return SWITCH_STATUS_FALSE; - } + if (ulaw_frame.payload != IANA_ULAW + && ulaw_frame.payload != IANACODE_CN) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read unexpected payload %d in Sangoma decoder RTP session, expecting %d\n", + ulaw_frame.payload, IANA_ULAW); + break; + } - /* transcode to linear */ - for (i = 0; i < ulaw_frame.datalen; i++) { - dbuf_linear[i] = ulaw_to_linear(((char *)ulaw_frame.data)[i]); + if (*decoded_data_len) { + sess->decoder.rxdiscarded++; + } + + /* transcode to linear */ + for (i = 0; i < ulaw_frame.datalen; i++) { + dbuf_linear[i] = ulaw_to_linear(((char *)ulaw_frame.data)[i]); + } + *decoded_data_len = i * 2; } - *decoded_data_len = i * 2; /* update decoding stats */ sess->decoder.rx++; @@ -708,6 +720,7 @@ SWITCH_STANDARD_API(sangoma_function) if (sess->encoder.rxrtp) { stats = switch_rtp_get_stats(sess->encoder.rxrtp, NULL); stream->write_function(stream, "-- Encoder Inbound Stats --\n"); + stream->write_function(stream, "Rx Discarded: %lu\n", sess->encoder.rxdiscarded); sangoma_print_stats(stream, &stats->inbound); @@ -719,6 +732,7 @@ SWITCH_STANDARD_API(sangoma_function) if (sess->decoder.rxrtp) { stats = switch_rtp_get_stats(sess->decoder.rxrtp, NULL); stream->write_function(stream, "-- Decoder Inbound Stats --\n"); + stream->write_function(stream, "Rx Discarded: %lu\n", sess->decoder.rxdiscarded); sangoma_print_stats(stream, &stats->inbound); stats = switch_rtp_get_stats(sess->decoder.txrtp, NULL); diff --git a/src/mod/endpoints/mod_skypopen/mod_skypopen.c b/src/mod/endpoints/mod_skypopen/mod_skypopen.c index 3c41524550..134e24ce32 100644 --- a/src/mod/endpoints/mod_skypopen/mod_skypopen.c +++ b/src/mod/endpoints/mod_skypopen/mod_skypopen.c @@ -179,6 +179,7 @@ static switch_status_t remove_interface(char *the_interface); static switch_status_t channel_on_init(switch_core_session_t *session); static switch_status_t channel_on_hangup(switch_core_session_t *session); +static switch_status_t channel_on_reset(switch_core_session_t *session); static switch_status_t channel_on_destroy(switch_core_session_t *session); static switch_status_t channel_on_routing(switch_core_session_t *session); static switch_status_t channel_on_exchange_media(switch_core_session_t *session); @@ -434,10 +435,6 @@ static switch_status_t channel_on_init(switch_core_session_t *session) where a destination has been identified. If the channel is simply left in the initial state, nothing will happen. */ switch_channel_set_state(channel, CS_ROUTING); - switch_mutex_lock(globals.mutex); - globals.calls++; - - switch_mutex_unlock(globals.mutex); DEBUGA_SKYPE("%s CHANNEL INIT %s\n", SKYPOPEN_P_LOG, tech_pvt->name, switch_core_session_get_uuid(session)); return SWITCH_STATUS_SUCCESS; @@ -645,6 +642,29 @@ static switch_status_t channel_on_soft_execute(switch_core_session_t *session) DEBUGA_SKYPE("%s CHANNEL SOFT_EXECUTE\n", SKYPOPEN_P_LOG, tech_pvt->name); return SWITCH_STATUS_SUCCESS; } +static switch_status_t channel_on_reset(switch_core_session_t *session) +{ + private_t *tech_pvt = NULL; + switch_channel_t *channel = NULL; + tech_pvt = switch_core_session_get_private(session); + DEBUGA_SKYPE("%s CHANNEL RESET\n", SKYPOPEN_P_LOG, tech_pvt->name); + + + if (session) { + channel = switch_core_session_get_channel(session); + } else { + ERRORA("No session???\n", SKYPOPEN_P_LOG); + } + if (channel) { + switch_channel_set_state(channel, CS_HANGUP); + } else { + ERRORA("No channel???\n", SKYPOPEN_P_LOG); + } + + + return SWITCH_STATUS_SUCCESS; +} + static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf) { @@ -824,10 +844,14 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc tech_pvt = switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); - if (!switch_channel_ready(channel) || !switch_test_flag(tech_pvt, TFLAG_IO)) { + if (!switch_channel_ready(channel)) { ERRORA("channel not ready \n", SKYPOPEN_P_LOG); return SWITCH_STATUS_FALSE; } + if (!switch_test_flag(tech_pvt, TFLAG_IO)) { + DEBUGA_SKYPE("channel not in TFLAG_IO \n", SKYPOPEN_P_LOG); + return SWITCH_STATUS_FALSE; + } #if SWITCH_BYTE_ORDER == __BIG_ENDIAN if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) { switch_swap_linear(frame->data, (int) frame->datalen / 2); @@ -865,6 +889,24 @@ static switch_status_t channel_answer_channel(switch_core_session_t *session) tech_pvt = switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); + switch_clear_flag(tech_pvt, TFLAG_IO); + skypopen_answer(tech_pvt); + + while(!switch_test_flag(tech_pvt, TFLAG_IO)){ //FIXME that would be better with a timeout + if(switch_channel_get_state(channel) == CS_RESET){ + return SWITCH_STATUS_FALSE; + } + switch_sleep(5000); + } + switch_mutex_lock(globals.mutex); + globals.calls++; + + switch_mutex_unlock(globals.mutex); + DEBUGA_SKYPE("%s CHANNEL ANSWER %s\n", SKYPOPEN_P_LOG, tech_pvt->name, switch_core_session_get_uuid(session)); + + + + DEBUGA_SKYPE("ANSWERED! \n", SKYPOPEN_P_LOG); return SWITCH_STATUS_SUCCESS; @@ -991,7 +1033,7 @@ switch_state_handler_table_t skypopen_state_handlers = { /*.on_soft_execute */ channel_on_soft_execute, /*.on_consume_media */ channel_on_consume_media, /*.on_hibernate */ NULL, - /*.on_reset */ NULL, + /*.on_reset */ channel_on_reset, /*.on_park */ NULL, /*.on_reporting */ NULL, /*.on_destroy */ channel_on_destroy @@ -1184,6 +1226,12 @@ static void *SWITCH_THREAD_FUNC skypopen_signaling_thread_func(switch_thread_t * *tech_pvt->session_uuid_str = '\0'; *tech_pvt->skype_call_id = '\0'; *tech_pvt->initial_skype_user = '\0'; + *tech_pvt->answer_id = '\0'; + *tech_pvt->answer_value = '\0'; + *tech_pvt->ring_id = '\0'; + *tech_pvt->ring_value = '\0'; + *tech_pvt->callid_number = '\0'; + *tech_pvt->callid_name = '\0'; switch_mutex_unlock(globals.mutex); switch_sleep(300000); //0.3 sec @@ -1949,7 +1997,6 @@ int new_inbound_channel(private_t * tech_pvt) } } if (channel) { - switch_channel_mark_answered(channel); switch_channel_set_variable(channel, "skype_user", tech_pvt->skype_user); switch_channel_set_variable(channel, "initial_skype_user", tech_pvt->initial_skype_user); } @@ -2261,34 +2308,149 @@ SWITCH_STANDARD_API(skypopen_function) return SWITCH_STATUS_SUCCESS; } -int skypopen_answer(private_t * tech_pvt, char *id, char *value) + +int skypopen_partner_handle_ring(private_t * tech_pvt) { char msg_to_skype[1024]; int i; int found = 0; private_t *giovatech; struct timeval timenow; + char *id = tech_pvt->ring_id; + char *value = tech_pvt->ring_value; + switch_core_session_t *session = NULL; + switch_channel_t *channel = NULL; switch_mutex_lock(globals.mutex); + //WARNINGA("PARTNER_HANDLE tech_pvt->skype_call_id=%s, tech_pvt->skype_callflow=%d, tech_pvt->interface_state=%d, tech_pvt->skype_user=%s, tech_pvt->callid_number=%s, tech_pvt->ring_value=%s, tech_pvt->ring_id=%s, tech_pvt->answer_value=%s, tech_pvt->answer_id=%s\n", SKYPOPEN_P_LOG, tech_pvt->skype_call_id, tech_pvt->skype_callflow, tech_pvt->interface_state, tech_pvt->skype_user, tech_pvt->callid_number, tech_pvt->ring_value, tech_pvt->ring_id, tech_pvt->answer_value, tech_pvt->answer_id); + gettimeofday(&timenow, NULL); for (i = 0; !found && i < SKYPOPEN_MAX_INTERFACES; i++) { if (strlen(globals.SKYPOPEN_INTERFACES[i].name)) { giovatech = &globals.SKYPOPEN_INTERFACES[i]; - if (strlen(giovatech->skype_call_id) && (giovatech->interface_state != SKYPOPEN_STATE_DOWN) && (!strcmp(giovatech->skype_user, tech_pvt->skype_user)) && (!strcmp(giovatech->callid_number, value)) && ((((timenow.tv_sec - giovatech->answer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech->answer_time.tv_usec)) < 1000000)) { //XXX 1.5sec - can have a max of 1 call coming from the same skypename to the same skypename each 1.5 seconds + if ((giovatech->interface_state != SKYPOPEN_STATE_DOWN) && (!strcmp(giovatech->skype_user, tech_pvt->skype_user)) && (!strcmp(giovatech->ring_value, value)) && ((((timenow.tv_sec - giovatech->ring_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech->ring_time.tv_usec)) < 1000000)) { //XXX 1.0sec - can have a max of 1 call coming from the same skypename to the same skypename each 1.0 seconds found = 1; - DEBUGA_SKYPE - ("FOUND (name=%s, giovatech->interface_state=%d != SKYPOPEN_STATE_DOWN) && (giovatech->skype_user=%s == tech_pvt->skype_user=%s) && (giovatech->callid_number=%s == value=%s)\n", - SKYPOPEN_P_LOG, giovatech->name, giovatech->interface_state, - giovatech->skype_user, tech_pvt->skype_user, giovatech->callid_number, value) - if (tech_pvt->interface_state == SKYPOPEN_STATE_PRERING) { + DEBUGA_SKYPE ("FOUND (name=%s, giovatech->interface_state=%d != SKYPOPEN_STATE_DOWN) && (giovatech->skype_user=%s == tech_pvt->skype_user=%s) && (giovatech->callid_number=%s == value=%s)\n", SKYPOPEN_P_LOG, giovatech->name, giovatech->interface_state, giovatech->skype_user, tech_pvt->skype_user, giovatech->callid_number, value); + if (tech_pvt->interface_state == SKYPOPEN_STATE_PRERING) { tech_pvt->interface_state = SKYPOPEN_STATE_DOWN; } else if (tech_pvt->interface_state != 0 && tech_pvt->interface_state != SKYPOPEN_STATE_DOWN) { WARNINGA("Why an interface_state %d HERE?\n", SKYPOPEN_P_LOG, tech_pvt->interface_state); tech_pvt->interface_state = SKYPOPEN_STATE_DOWN; } + *tech_pvt->answer_id = '\0'; + *tech_pvt->answer_value = '\0'; + *tech_pvt->ring_id = '\0'; + *tech_pvt->ring_value = '\0'; + break; + } + } + } + + if (found) { + switch_mutex_unlock(globals.mutex); + return 0; + } + DEBUGA_SKYPE("NOT FOUND\n", SKYPOPEN_P_LOG); + + if (tech_pvt && tech_pvt->skype_call_id && !strlen(tech_pvt->skype_call_id)) { + /* we are not inside an active call */ + + tech_pvt->interface_state = SKYPOPEN_STATE_PRERING; + gettimeofday(&tech_pvt->ring_time, NULL); + switch_copy_string(tech_pvt->callid_number, value, sizeof(tech_pvt->callid_number) - 1); + + + //WARNINGA("PARTNER_HANDLE_RING tech_pvt->skype_call_id=%s, tech_pvt->skype_callflow=%d, tech_pvt->interface_state=%d, tech_pvt->skype_user=%s, tech_pvt->callid_number=%s, tech_pvt->ring_value=%s, tech_pvt->ring_id=%s, tech_pvt->answer_value=%s, tech_pvt->answer_id=%s\n", SKYPOPEN_P_LOG, tech_pvt->skype_call_id, tech_pvt->skype_callflow, tech_pvt->interface_state, tech_pvt->skype_user, tech_pvt->callid_number, tech_pvt->ring_value, tech_pvt->ring_id, tech_pvt->answer_value, tech_pvt->answer_id); + + session = switch_core_session_locate(tech_pvt->session_uuid_str); + if (session) { + switch_core_session_rwunlock(session); + return 0; + } + + new_inbound_channel(tech_pvt); + + session = switch_core_session_locate(tech_pvt->session_uuid_str); + if (session) { + channel = switch_core_session_get_channel(session); + + switch_core_session_queue_indication(session, SWITCH_MESSAGE_INDICATE_RINGING); + if (channel) { + switch_channel_mark_ring_ready(channel); + } else { + ERRORA("no channel\n", SKYPOPEN_P_LOG); + } + switch_core_session_rwunlock(session); + } else { + ERRORA("no session\n", SKYPOPEN_P_LOG); + + } + + } else if (!tech_pvt || !tech_pvt->skype_call_id) { + ERRORA("No Call ID?\n", SKYPOPEN_P_LOG); + } else { + DEBUGA_SKYPE("We're in a call now (%s), let's refuse this one (%s)\n", SKYPOPEN_P_LOG, tech_pvt->skype_call_id, id); + sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id); + skypopen_signaling_write(tech_pvt, msg_to_skype); + } + + switch_mutex_unlock(globals.mutex); + return 0; +} + +int skypopen_answer(private_t * tech_pvt) +{ + char msg_to_skype[1024]; + int i; + int found = 0; + private_t *giovatech; + struct timeval timenow; + char *id = tech_pvt->answer_id; + char *value = tech_pvt->answer_value; + switch_core_session_t *session = NULL; + switch_channel_t *channel = NULL; + + switch_mutex_lock(globals.mutex); + + //WARNINGA("ANSWER tech_pvt->skype_call_id=%s, tech_pvt->skype_callflow=%d, tech_pvt->interface_state=%d, tech_pvt->skype_user=%s, tech_pvt->callid_number=%s, tech_pvt->ring_value=%s, tech_pvt->ring_id=%s, tech_pvt->answer_value=%s, tech_pvt->answer_id=%s\n", SKYPOPEN_P_LOG, tech_pvt->skype_call_id, tech_pvt->skype_callflow, tech_pvt->interface_state, tech_pvt->skype_user, tech_pvt->callid_number, tech_pvt->ring_value, tech_pvt->ring_id, tech_pvt->answer_value, tech_pvt->answer_id); + + gettimeofday(&timenow, NULL); + for (i = 0; !found && i < SKYPOPEN_MAX_INTERFACES; i++) { + if (strlen(globals.SKYPOPEN_INTERFACES[i].name)) { + + giovatech = &globals.SKYPOPEN_INTERFACES[i]; + if (strlen(giovatech->skype_call_id) && (giovatech->interface_state != SKYPOPEN_STATE_DOWN) && (!strcmp(giovatech->skype_user, tech_pvt->skype_user)) && (!strcmp(giovatech->callid_number, value)) && ((((timenow.tv_sec - giovatech->answer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech->answer_time.tv_usec)) < 1000000)) { //XXX 1.0sec - can have a max of 1 call coming from the same skypename to the same skypename each 1.0 seconds + found = 1; + DEBUGA_SKYPE ("FOUND (name=%s, giovatech->interface_state=%d != SKYPOPEN_STATE_DOWN) && (giovatech->skype_user=%s == tech_pvt->skype_user=%s) && (giovatech->callid_number=%s == value=%s)\n", SKYPOPEN_P_LOG, giovatech->name, giovatech->interface_state, giovatech->skype_user, tech_pvt->skype_user, giovatech->callid_number, value); + if (tech_pvt->interface_state == SKYPOPEN_STATE_PRERING) { + tech_pvt->interface_state = SKYPOPEN_STATE_DOWN; + } else if (tech_pvt->interface_state != 0 && tech_pvt->interface_state != SKYPOPEN_STATE_DOWN) { + WARNINGA("Why an interface_state %d HERE?\n", SKYPOPEN_P_LOG, tech_pvt->interface_state); + tech_pvt->interface_state = SKYPOPEN_STATE_DOWN; + } + + + if (!zstr(tech_pvt->session_uuid_str)) { + session = switch_core_session_locate(tech_pvt->session_uuid_str); + } else { + ERRORA("No session???\n", SKYPOPEN_P_LOG); + } + if (session) { + channel = switch_core_session_get_channel(session); + } else { + ERRORA("No session???\n", SKYPOPEN_P_LOG); + } + if (channel) { + switch_channel_set_state(channel, CS_RESET); + } else { + ERRORA("No channel???\n", SKYPOPEN_P_LOG); + } + + switch_core_session_rwunlock(session); + break; } } @@ -2305,9 +2467,6 @@ int skypopen_answer(private_t * tech_pvt, char *id, char *value) tech_pvt->ib_calls++; - sprintf(msg_to_skype, "GET CALL %s PARTNER_DISPNAME", id); - skypopen_signaling_write(tech_pvt, msg_to_skype); - switch_sleep(10000); tech_pvt->interface_state = SKYPOPEN_STATE_PREANSWER; sprintf(msg_to_skype, "ALTER CALL %s ANSWER", id); skypopen_signaling_write(tech_pvt, msg_to_skype); diff --git a/src/mod/endpoints/mod_skypopen/skypopen.h b/src/mod/endpoints/mod_skypopen/skypopen.h index b978623fd5..b991f0e8a7 100644 --- a/src/mod/endpoints/mod_skypopen/skypopen.h +++ b/src/mod/endpoints/mod_skypopen/skypopen.h @@ -264,6 +264,7 @@ struct private_object { char skype_password[256]; char destination[256]; struct timeval answer_time; + struct timeval ring_time; struct timeval transfer_time; char transfer_callid_number[50]; @@ -288,6 +289,10 @@ struct private_object { int silent_mode; int write_silence_when_idle; int setsockopt; + char answer_id[256]; + char answer_value[256]; + char ring_id[256]; + char ring_value[256]; }; @@ -328,7 +333,8 @@ int skypopen_close_socket(unsigned int fd); private_t *find_available_skypopen_interface_rr(private_t * tech_pvt_calling); int remote_party_is_ringing(private_t * tech_pvt); int remote_party_is_early_media(private_t * tech_pvt); -int skypopen_answer(private_t * tech_pvt, char *id, char *value); +//int skypopen_answer(private_t * tech_pvt, char *id, char *value); +int skypopen_answer(private_t * tech_pvt); int skypopen_transfer(private_t * tech_pvt, char *id, char *value); #ifndef WIN32 int skypopen_socket_create_and_bind(private_t * tech_pvt, int *which_port); @@ -337,3 +343,6 @@ int skypopen_socket_create_and_bind(private_t * tech_pvt, unsigned short *which_ #endif //WIN32 int incoming_chatmessage(private_t * tech_pvt, int which); int next_port(void); +int skypopen_partner_handle_ring(private_t * tech_pvt); +int skypopen_answered(private_t * tech_pvt); +int inbound_channel_answered(private_t * tech_pvt); diff --git a/src/mod/endpoints/mod_skypopen/skypopen_protocol.c b/src/mod/endpoints/mod_skypopen/skypopen_protocol.c index 6f4fc33b65..a15b5643aa 100644 --- a/src/mod/endpoints/mod_skypopen/skypopen_protocol.c +++ b/src/mod/endpoints/mod_skypopen/skypopen_protocol.c @@ -214,7 +214,7 @@ int skypopen_signaling_read(private_t * tech_pvt) ERRORA("Skype got ERROR: |||%s|||, another call is active on this interface\n\n\n", SKYPOPEN_P_LOG, message); tech_pvt->interface_state = SKYPOPEN_STATE_ERROR_DOUBLE_CALL; } else if (!strncasecmp(message, "ERROR 592 ALTER CALL", 19)) { - ERRORA("Skype got ERROR about TRANSFERRING, no problem: |||%s|||\n", SKYPOPEN_P_LOG, message); + NOTICA("Skype got ERROR about TRANSFERRING, no problem: |||%s|||\n", SKYPOPEN_P_LOG, message); } else if (!strncasecmp(message, "ERROR 559 CALL", 13)) { if (tech_pvt->interface_state == SKYPOPEN_STATE_PREANSWER) { DEBUGA_SKYPE("Skype got ERROR about a failed action (probably TRYING to ANSWER A CALL), let's go down: |||%s|||\n", SKYPOPEN_P_LOG, @@ -478,8 +478,12 @@ int skypopen_signaling_read(private_t * tech_pvt) if (!strcasecmp(prop, "PARTNER_HANDLE")) { if (tech_pvt->interface_state != SKYPOPEN_STATE_SELECTED && (!strlen(tech_pvt->skype_call_id) || !strlen(tech_pvt->session_uuid_str))) { /* we are NOT inside an active call */ - DEBUGA_SKYPE("Call %s TRY ANSWER\n", SKYPOPEN_P_LOG, id); - skypopen_answer(tech_pvt, id, value); + DEBUGA_SKYPE("Call %s go to skypopen_partner_handle_ring\n", SKYPOPEN_P_LOG, id); + skypopen_strncpy(tech_pvt->ring_id, id, sizeof(tech_pvt->ring_id)); + skypopen_strncpy(tech_pvt->ring_value, value, sizeof(tech_pvt->ring_value)); + skypopen_strncpy(tech_pvt->answer_id, id, sizeof(tech_pvt->answer_id)); + skypopen_strncpy(tech_pvt->answer_value, value, sizeof(tech_pvt->answer_value)); + skypopen_partner_handle_ring(tech_pvt); } else { /* we are inside an active call */ if (!strcasecmp(tech_pvt->skype_call_id, id)) { @@ -553,7 +557,10 @@ int skypopen_signaling_read(private_t * tech_pvt) && (!strlen(tech_pvt->skype_call_id) || !strlen(tech_pvt->session_uuid_str))) { /* we are NOT inside an active call */ - DEBUGA_SKYPE("NO ACTIVE calls in this moment, skype_call %s is RINGING, to ask PARTNER_HANDLE\n", SKYPOPEN_P_LOG, id); + DEBUGA_SKYPE("NO ACTIVE calls in this moment, skype_call %s is RINGING, to ask PARTNER_DISPNAME and PARTNER_HANDLE\n", SKYPOPEN_P_LOG, id); + sprintf(msg_to_skype, "GET CALL %s PARTNER_DISPNAME", id); + skypopen_signaling_write(tech_pvt, msg_to_skype); + skypopen_sleep(100); sprintf(msg_to_skype, "GET CALL %s PARTNER_HANDLE", id); skypopen_signaling_write(tech_pvt, msg_to_skype); skypopen_sleep(10000); @@ -684,14 +691,7 @@ int skypopen_signaling_read(private_t * tech_pvt) skypopen_signaling_write(tech_pvt, msg_to_skype); } tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS; - if (!strlen(tech_pvt->session_uuid_str)) { - DEBUGA_SKYPE("New Inbound Channel!\n\n\n\n", SKYPOPEN_P_LOG); - new_inbound_channel(tech_pvt); - } else { - tech_pvt->interface_state = SKYPOPEN_STATE_UP; - DEBUGA_SKYPE("Outbound Channel Answered! session_uuid_str=%s\n", SKYPOPEN_P_LOG, tech_pvt->session_uuid_str); - outbound_channel_answered(tech_pvt); - } + skypopen_answered(tech_pvt); } else { DEBUGA_SKYPE("I'm on %s, skype_call %s is NOT MY call, ignoring\n", SKYPOPEN_P_LOG, tech_pvt->skype_call_id, id); } @@ -1752,3 +1752,61 @@ while(XPending(disp)){ } #endif // WIN32 + +int inbound_channel_answered(private_t * tech_pvt) +{ + int res = 0; + switch_core_session_t *session = NULL; + switch_channel_t *channel = NULL; + + session = switch_core_session_locate(tech_pvt->session_uuid_str); + if (session) { + channel = switch_core_session_get_channel(session); + + if (channel) { + switch_set_flag(tech_pvt, TFLAG_IO); + } else { + ERRORA("no channel\n", SKYPOPEN_P_LOG); + } + switch_core_session_rwunlock(session); + } else { + ERRORA("no session\n", SKYPOPEN_P_LOG); + + } + return res; +} + + +int skypopen_answered(private_t * tech_pvt) +{ + + int res = 0; + switch_core_session_t *session = NULL; + switch_channel_t *channel = NULL; + + //WARNINGA("ANSWERED tech_pvt->skype_call_id=%s, tech_pvt->skype_callflow=%d, tech_pvt->interface_state=%d, tech_pvt->skype_user=%s, tech_pvt->callid_number=%s, tech_pvt->ring_value=%s, tech_pvt->ring_id=%s, tech_pvt->answer_value=%s, tech_pvt->answer_id=%s\n", SKYPOPEN_P_LOG, tech_pvt->skype_call_id, tech_pvt->skype_callflow, tech_pvt->interface_state, tech_pvt->skype_user, tech_pvt->callid_number, tech_pvt->ring_value, tech_pvt->ring_id, tech_pvt->answer_value, tech_pvt->answer_id); + + session = switch_core_session_locate(tech_pvt->session_uuid_str); + if (session) { + channel = switch_core_session_get_channel(session); + + if (channel) { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { + tech_pvt->interface_state = SKYPOPEN_STATE_UP; + DEBUGA_SKYPE("Outbound Channel Answered! session_uuid_str=%s\n", SKYPOPEN_P_LOG, tech_pvt->session_uuid_str); + outbound_channel_answered(tech_pvt); + } else { + DEBUGA_SKYPE("answered Inbound Channel!\n\n\n\n", SKYPOPEN_P_LOG); + inbound_channel_answered(tech_pvt); + } + + } else { + ERRORA("no channel\n", SKYPOPEN_P_LOG); + } + switch_core_session_rwunlock(session); + } else { + ERRORA("no session\n", SKYPOPEN_P_LOG); + + } + return res; +}