From fd2bf49b7c3de75723c1b3959c48032e730f5433 Mon Sep 17 00:00:00 2001 From: Giovanni Maruzzelli Date: Fri, 14 Aug 2009 17:12:09 +0000 Subject: [PATCH] skypiax: ubermegapatch, more stability, robustness, scalability. Memory leaks not yet investigated, we'll do next git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@14517 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/mod/endpoints/mod_skypiax/mod_skypiax.c | 212 ++++++++++++------ src/mod/endpoints/mod_skypiax/skypiax.h | 6 +- .../endpoints/mod_skypiax/skypiax_protocol.c | 196 +++++++++++++--- 3 files changed, 318 insertions(+), 96 deletions(-) diff --git a/src/mod/endpoints/mod_skypiax/mod_skypiax.c b/src/mod/endpoints/mod_skypiax/mod_skypiax.c index a80f25ea6b..f75fe3925a 100644 --- a/src/mod/endpoints/mod_skypiax/mod_skypiax.c +++ b/src/mod/endpoints/mod_skypiax/mod_skypiax.c @@ -148,6 +148,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id); static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id); static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig); +static switch_status_t skypiax_tech_init(private_t * tech_pvt, switch_core_session_t *session); static switch_status_t skypiax_codec(private_t * tech_pvt, int sample_rate, int codec_ms) { @@ -173,30 +174,40 @@ static switch_status_t skypiax_codec(private_t * tech_pvt, int sample_rate, int session = switch_core_session_locate(tech_pvt->session_uuid_str); - switch_core_session_set_read_codec(session, &tech_pvt->read_codec); - switch_core_session_set_write_codec(session, &tech_pvt->write_codec); - - switch_core_session_rwunlock(session); + if(session){ + switch_core_session_set_read_codec(session, &tech_pvt->read_codec); + switch_core_session_set_write_codec(session, &tech_pvt->write_codec); + switch_core_session_rwunlock(session); + } else { + ERRORA("no session\n", SKYPIAX_P_LOG); + return SWITCH_STATUS_FALSE; + } return SWITCH_STATUS_SUCCESS; } -void skypiax_tech_init(private_t * tech_pvt, switch_core_session_t *session) +switch_status_t skypiax_tech_init(private_t * tech_pvt, switch_core_session_t *session) { + switch_assert(tech_pvt != NULL); + switch_assert(session != NULL); tech_pvt->read_frame.data = tech_pvt->databuf; tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf); switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); switch_core_session_set_private(session, tech_pvt); switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(session), sizeof(tech_pvt->session_uuid_str)); + if(!strlen(tech_pvt->session_uuid_str)){ + ERRORA("no tech_pvt->session_uuid_str\n", SKYPIAX_P_LOG); + return SWITCH_STATUS_FALSE; + } if (skypiax_codec(tech_pvt, SAMPLERATE_SKYPIAX, 20) != SWITCH_STATUS_SUCCESS) { ERRORA("skypiax_codec FAILED\n", SKYPIAX_P_LOG); - } else { - DEBUGA_SKYPE("skypiax_codec SUCCESS\n", SKYPIAX_P_LOG); + return SWITCH_STATUS_FALSE; } - + DEBUGA_SKYPE("skypiax_codec SUCCESS\n", SKYPIAX_P_LOG); + return SWITCH_STATUS_SUCCESS; } /* BEGIN: Changes here */ @@ -364,7 +375,8 @@ static switch_status_t channel_on_init(switch_core_session_t *session) channel = switch_core_session_get_channel(session); switch_assert(channel != NULL); - switch_set_flag_locked(tech_pvt, TFLAG_IO); + DEBUGA_SKYPE("%s CHANNEL INIT\n", SKYPIAX_P_LOG, switch_channel_get_name(channel)); + switch_set_flag(tech_pvt, TFLAG_IO); /* Move channel's state machine to ROUTING. This means the call is trying to get from the initial start where the call because, to the point @@ -376,7 +388,6 @@ static switch_status_t channel_on_init(switch_core_session_t *session) switch_mutex_unlock(globals.mutex); - DEBUGA_SKYPE("%s CHANNEL INIT\n", SKYPIAX_P_LOG, switch_channel_get_name(channel)); return SWITCH_STATUS_SUCCESS; } @@ -394,6 +405,7 @@ static switch_status_t channel_on_destroy(switch_core_session_t *session) if (switch_core_codec_ready(&tech_pvt->write_codec)) { switch_core_codec_destroy(&tech_pvt->write_codec); } + *tech_pvt->session_uuid_str = '\0'; switch_core_session_set_private(session, NULL); } @@ -406,15 +418,16 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) private_t *tech_pvt = NULL; char msg_to_skype[256]; + channel = switch_core_session_get_channel(session); switch_assert(channel != NULL); tech_pvt = switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); - switch_clear_flag_locked(tech_pvt, TFLAG_IO); - switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); - //switch_set_flag_locked(tech_pvt, TFLAG_HANGUP); + switch_clear_flag(tech_pvt, TFLAG_IO); + switch_clear_flag(tech_pvt, TFLAG_VOICE); + //switch_set_flag(tech_pvt, TFLAG_HANGUP); if (strlen(tech_pvt->skype_call_id)) { //switch_thread_cond_signal(tech_pvt->cond); @@ -423,7 +436,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) skypiax_signaling_write(tech_pvt, msg_to_skype); } //memset(tech_pvt->session_uuid_str, '\0', sizeof(tech_pvt->session_uuid_str)); - *tech_pvt->session_uuid_str = '\0'; + //*tech_pvt->session_uuid_str = '\0'; DEBUGA_SKYPE("%s CHANNEL HANGUP\n", SKYPIAX_P_LOG, switch_channel_get_name(channel)); switch_mutex_lock(globals.mutex); globals.calls--; @@ -482,13 +495,18 @@ static switch_status_t channel_kill_channel(switch_core_session_t *session, int switch (sig) { case SWITCH_SIG_KILL: DEBUGA_SKYPE("%s CHANNEL got SWITCH_SIG_KILL\n", SKYPIAX_P_LOG, switch_channel_get_name(channel)); - switch_clear_flag_locked(tech_pvt, TFLAG_IO); - switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); - switch_set_flag_locked(tech_pvt, TFLAG_HANGUP); + //switch_mutex_lock(tech_pvt->flag_mutex); + switch_clear_flag(tech_pvt, TFLAG_IO); + switch_clear_flag(tech_pvt, TFLAG_VOICE); + switch_set_flag(tech_pvt, TFLAG_HANGUP); + //switch_mutex_unlock(tech_pvt->flag_mutex); break; case SWITCH_SIG_BREAK: DEBUGA_SKYPE("%s CHANNEL got SWITCH_SIG_BREAK\n", SKYPIAX_P_LOG, switch_channel_get_name(channel)); - switch_set_flag_locked(tech_pvt, TFLAG_BREAK); + //switch_set_flag(tech_pvt, TFLAG_BREAK); + //switch_mutex_lock(tech_pvt->flag_mutex); + switch_set_flag(tech_pvt, TFLAG_BREAK); + //switch_mutex_unlock(tech_pvt->flag_mutex); break; default: break; @@ -536,7 +554,8 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch switch_assert(tech_pvt != NULL); if (!switch_channel_ready(channel) || !switch_test_flag(tech_pvt, TFLAG_IO)) { - ERRORA("CIAPA \n", SKYPIAX_P_LOG); + ERRORA("channel not ready \n", SKYPIAX_P_LOG); + //TODO: kill the bastard return SWITCH_STATUS_FALSE; } @@ -548,7 +567,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch ERRORA("skypiax_audio_read ERROR\n", SKYPIAX_P_LOG); } else { - switch_set_flag_locked(tech_pvt, TFLAG_VOICE); + switch_set_flag(tech_pvt, TFLAG_VOICE); } while (switch_test_flag(tech_pvt, TFLAG_IO)) { @@ -564,7 +583,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch } if (switch_test_flag(tech_pvt, TFLAG_IO) && switch_test_flag(tech_pvt, TFLAG_VOICE)) { - switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); + switch_clear_flag(tech_pvt, TFLAG_VOICE); if (!tech_pvt->read_frame.datalen) { DEBUGA_SKYPE("CHANNEL READ CONTINUE\n", SKYPIAX_P_LOG); continue; @@ -610,7 +629,8 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc switch_assert(tech_pvt != NULL); if (!switch_channel_ready(channel) || !switch_test_flag(tech_pvt, TFLAG_IO)) { - ERRORA("CIAPA \n", SKYPIAX_P_LOG); + ERRORA("channel not ready \n", SKYPIAX_P_LOG); + //TODO: kill the bastard return SWITCH_STATUS_FALSE; } #ifdef BIGENDIAN @@ -721,9 +741,9 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi switch_caller_profile_t *outbound_profile, switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags) { - if ((*new_session = switch_core_session_request(skypiax_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, pool)) != 0) { private_t *tech_pvt = NULL; - switch_channel_t *channel; + if ((*new_session = switch_core_session_request(skypiax_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, pool)) != 0) { + switch_channel_t *channel = NULL; switch_caller_profile_t *caller_profile; char *rdest; int found = 0; @@ -741,16 +761,16 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi *slash = '\0'; switch_mutex_lock(globals.mutex); - if (strncmp("ANY", interface_name, strlen(interface_name)) == 0) { + if (strncmp("ANY", interface_name, strlen(interface_name)) == 0 || strncmp("RR", interface_name, strlen(interface_name)) == 0) { /* we've been asked for the "ANY" interface, let's find the first idle interface */ - DEBUGA_SKYPE("Finding one available skype interface\n", SKYPIAX_P_LOG); - tech_pvt = find_available_skypiax_interface(NULL); - if (tech_pvt) - found = 1; - } else if (strncmp("RR", interface_name, strlen(interface_name)) == 0) { + //DEBUGA_SKYPE("Finding one available skype interface\n", SKYPIAX_P_LOG); + //tech_pvt = find_available_skypiax_interface(NULL); + //if (tech_pvt) + //found = 1; + //} else if (strncmp("RR", interface_name, strlen(interface_name)) == 0) { /* Find the first idle interface using Round Robin */ DEBUGA_SKYPE("Finding one available skype interface RR\n", SKYPIAX_P_LOG); - tech_pvt = find_available_skypiax_interface_rr(); + tech_pvt = find_available_skypiax_interface_rr(NULL); if (tech_pvt) found = 1; } @@ -765,7 +785,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi SKYPIAX_P_LOG, i, globals.SKYPIAX_INTERFACES[i].name, globals.SKYPIAX_INTERFACES[i].session_uuid_str); switch_core_session_destroy(new_session); switch_mutex_unlock(globals.mutex); - return SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE; + return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; } DEBUGA_SKYPE("globals.SKYPIAX_INTERFACES[%d].name=|||%s|||?\n", SKYPIAX_P_LOG, i, globals.SKYPIAX_INTERFACES[i].name); @@ -783,14 +803,26 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi } if (!found) { - ERRORA("Doh! no matching interface for |||%s|||?\n", SKYPIAX_P_LOG, interface_name); + DEBUGA_SKYPE("Doh! no available interface for |||%s|||?\n", SKYPIAX_P_LOG, interface_name); + switch_core_session_destroy(new_session); + switch_mutex_unlock(globals.mutex); + //return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; + return SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION; + } + + channel = switch_core_session_get_channel(*new_session); + if(!channel){ + ERRORA("Doh! no channel?\n", SKYPIAX_P_LOG); + switch_core_session_destroy(new_session); + switch_mutex_unlock(globals.mutex); + return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; + } + if( skypiax_tech_init(tech_pvt, *new_session) != SWITCH_STATUS_SUCCESS){ + ERRORA("Doh! no tech_init?\n", SKYPIAX_P_LOG); switch_core_session_destroy(new_session); switch_mutex_unlock(globals.mutex); return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; } - - channel = switch_core_session_get_channel(*new_session); - skypiax_tech_init(tech_pvt, *new_session); if (outbound_profile) { @@ -812,19 +844,21 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi rdest = strchr(caller_profile->destination_number, '/'); *rdest++ = '\0'; - skypiax_call(tech_pvt, rdest, 30); + //skypiax_call(tech_pvt, rdest, 30); switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(*new_session), sizeof(tech_pvt->session_uuid_str)); caller_profile = tech_pvt->caller_profile; caller_profile->destination_number = rdest; switch_channel_set_flag(channel, CF_OUTBOUND); - switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND); + switch_set_flag(tech_pvt, TFLAG_OUTBOUND); switch_channel_set_state(channel, CS_INIT); + skypiax_call(tech_pvt, rdest, 30); switch_mutex_unlock(globals.mutex); return SWITCH_CAUSE_SUCCESS; } + ERRORA("Doh! no new_session\n", SKYPIAX_P_LOG); return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; } @@ -849,29 +883,35 @@ static void *SWITCH_THREAD_FUNC skypiax_signaling_thread_func(switch_thread_t * res = skypiax_signaling_read(tech_pvt); if (res == CALLFLOW_INCOMING_HANGUP) { switch_core_session_t *session = NULL; - //private_t *tech_pvt = NULL; switch_channel_t *channel = NULL; - + //private_t *tech_pvt = NULL; DEBUGA_SKYPE("skype call ended\n", SKYPIAX_P_LOG); if (tech_pvt) { session = switch_core_session_locate(tech_pvt->session_uuid_str); - if (session) { channel = switch_core_session_get_channel(session); if (channel) { + switch_channel_state_t state = switch_channel_get_state(channel); + if(state < CS_EXECUTE){ + usleep(10000);//10 msec, let the state evolve from CS_NEW + } switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); - switch_core_session_rwunlock(session); } else { ERRORA("no channel?\n", SKYPIAX_P_LOG); - switch_core_session_rwunlock(session); } + switch_core_session_rwunlock(session); } else { DEBUGA_SKYPE("no session\n", SKYPIAX_P_LOG); } tech_pvt->interface_state = SKYPIAX_STATE_DOWN; *tech_pvt->session_uuid_str = '\0'; - //memset(tech_pvt->session_uuid_str, '\0', sizeof(tech_pvt->session_uuid_str)); + *tech_pvt->skype_call_id = '\0'; + + //ERRORA("LET'S WAIT\n", SKYPIAX_P_LOG); + usleep(300000); //0.3 sec + //ERRORA("WAIT'S OVER\n", SKYPIAX_P_LOG); + tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED; } else { ERRORA("no tech_pvt?\n", SKYPIAX_P_LOG); } @@ -1389,16 +1429,29 @@ int start_audio_threads(private_t * tech_pvt) switch_threadattr_create(&thd_attr, skypiax_module_pool); switch_threadattr_detach_set(thd_attr, 1); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_thread_create(&tech_pvt->tcp_srv_thread, thd_attr, skypiax_do_tcp_srv_thread, tech_pvt, skypiax_module_pool); + if (switch_thread_create(&tech_pvt->tcp_srv_thread, thd_attr, skypiax_do_tcp_srv_thread, tech_pvt, skypiax_module_pool) == SWITCH_STATUS_SUCCESS) { DEBUGA_SKYPE("started tcp_srv_thread thread.\n", SKYPIAX_P_LOG); + } else { + ERRORA("failed to start tcp_srv_thread thread.\n", SKYPIAX_P_LOG); + return -1; + } switch_threadattr_create(&thd_attr, skypiax_module_pool); switch_threadattr_detach_set(thd_attr, 1); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_thread_create(&tech_pvt->tcp_cli_thread, thd_attr, skypiax_do_tcp_cli_thread, tech_pvt, skypiax_module_pool); + if(switch_thread_create(&tech_pvt->tcp_cli_thread, thd_attr, skypiax_do_tcp_cli_thread, tech_pvt, skypiax_module_pool) == SWITCH_STATUS_SUCCESS) { DEBUGA_SKYPE("started tcp_cli_thread thread.\n", SKYPIAX_P_LOG); + }else{ + ERRORA("failed to start tcp_cli_thread thread.\n", SKYPIAX_P_LOG); + return -1; + } switch_sleep(100000); + if(tech_pvt->tcp_cli_thread == NULL || tech_pvt->tcp_srv_thread == NULL) { + ERRORA("tcp_cli_thread or tcp_srv_thread exited\n", SKYPIAX_P_LOG); + return -1; + } + return 0; } @@ -1410,7 +1463,16 @@ int new_inbound_channel(private_t * tech_pvt) if ((session = switch_core_session_request(skypiax_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, NULL)) != 0) { switch_core_session_add_stream(session, NULL); channel = switch_core_session_get_channel(session); - skypiax_tech_init(tech_pvt, session); + if(!channel){ + ERRORA("Doh! no channel?\n", SKYPIAX_P_LOG); + switch_core_session_destroy(&session); + return 0; + } + if( skypiax_tech_init(tech_pvt, session) != SWITCH_STATUS_SUCCESS){ + ERRORA("Doh! no tech_init?\n", SKYPIAX_P_LOG); + switch_core_session_destroy(&session); + return 0; + } if ((tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session), "skypiax", @@ -1426,11 +1488,14 @@ int new_inbound_channel(private_t * tech_pvt) if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) { ERRORA("Error spawning thread\n", SKYPIAX_P_LOG); switch_core_session_destroy(&session); + return 0; } } - switch_channel_mark_answered(channel); + if(channel){ + switch_channel_mark_answered(channel); + } - DEBUGA_SKYPE("Here\n", SKYPIAX_P_LOG); + DEBUGA_SKYPE("new_inbound_channel\n", SKYPIAX_P_LOG); return 0; } @@ -1457,7 +1522,6 @@ int remote_party_is_ringing(private_t * tech_pvt) DEBUGA_SKYPE("skype_call: REMOTE PARTY RINGING\n", SKYPIAX_P_LOG); } else { ERRORA("No channel???\n", SKYPIAX_P_LOG); - goto done; } switch_core_session_rwunlock(session); @@ -1474,7 +1538,8 @@ int remote_party_is_early_media(private_t * tech_pvt) if (!switch_strlen_zero(tech_pvt->session_uuid_str)) { session = switch_core_session_locate(tech_pvt->session_uuid_str); } else { - ERRORA("No session???\n", SKYPIAX_P_LOG); + ERRORA("No session???\n\n\n", SKYPIAX_P_LOG); + //TODO: kill the bastard goto done; } if (session) { @@ -1482,6 +1547,7 @@ int remote_party_is_early_media(private_t * tech_pvt) switch_core_session_add_stream(session, NULL); } else { ERRORA("No session???\n", SKYPIAX_P_LOG); + //TODO: kill the bastard goto done; } if (channel) { @@ -1489,7 +1555,7 @@ int remote_party_is_early_media(private_t * tech_pvt) DEBUGA_SKYPE("skype_call: REMOTE PARTY EARLY MEDIA\n", SKYPIAX_P_LOG); } else { ERRORA("No channel???\n", SKYPIAX_P_LOG); - goto done; + //TODO: kill the bastard } switch_core_session_rwunlock(session); @@ -1512,7 +1578,7 @@ int outbound_channel_answered(private_t * tech_pvt) if (session) { channel = switch_core_session_get_channel(session); } else { - ERRORA("No session???\n", SKYPIAX_P_LOG); + ERRORA("No channel???\n", SKYPIAX_P_LOG); goto done; } if (channel) { @@ -1520,17 +1586,17 @@ int outbound_channel_answered(private_t * tech_pvt) //DEBUGA_SKYPE("skype_call: %s, answered\n", SKYPIAX_P_LOG, id); } else { ERRORA("No channel???\n", SKYPIAX_P_LOG); - goto done; } switch_core_session_rwunlock(session); done: - DEBUGA_SKYPE("HERE!\n", SKYPIAX_P_LOG); + DEBUGA_SKYPE("outbound_channel_answered!\n", SKYPIAX_P_LOG); return 0; } +#if 0 private_t *find_available_skypiax_interface(private_t * tech_pvt) { private_t *tech_pvt2 = NULL; @@ -1559,8 +1625,9 @@ private_t *find_available_skypiax_interface(private_t * tech_pvt) else return NULL; } +#endif -private_t *find_available_skypiax_interface_rr(void) +private_t *find_available_skypiax_interface_rr(private_t * tech_pvt_calling) { private_t *tech_pvt = NULL; int i; @@ -1585,12 +1652,14 @@ private_t *find_available_skypiax_interface_rr(void) tech_pvt = &globals.SKYPIAX_INTERFACES[interface_id]; skype_state = tech_pvt->interface_state; - DEBUGA_SKYPE("skype interface: %d, name: %s, state: %d\n", SKYPIAX_P_LOG, interface_id, - globals.SKYPIAX_INTERFACES[interface_id].name, skype_state); - if (SKYPIAX_STATE_DOWN == skype_state || 0 == skype_state) { + //DEBUGA_SKYPE("skype interface: %d, name: %s, state: %d\n", SKYPIAX_P_LOG, interface_id, globals.SKYPIAX_INTERFACES[interface_id].name, skype_state); + if ((tech_pvt_calling ? strcmp(tech_pvt->skype_user, tech_pvt_calling->skype_user) : 1) && (SKYPIAX_STATE_DOWN == skype_state || 0 == skype_state) && (tech_pvt->skype_callflow ==CALLFLOW_STATUS_FINISHED || 0 == tech_pvt->skype_callflow )) { + DEBUGA_SKYPE("returning as available skype interface name: %s, state: %d callflow: %d\n", SKYPIAX_P_LOG, tech_pvt->name, skype_state, tech_pvt->skype_callflow); /*set to Dialing state to avoid other thread fint it, don't know if it is safe */ //XXX no, it's not safe - //tech_pvt->interface_state = SKYPIAX_STATE_DIALING ; + if(tech_pvt_calling == NULL){ + tech_pvt->interface_state = SKYPIAX_STATE_SELECTED ; + } switch_mutex_unlock(globals.mutex); return tech_pvt; @@ -1796,6 +1865,8 @@ int skypiax_answer(private_t * tech_pvt, char *id, char *value) if (found) { //tech_pvt->callid_number[0]='\0'; + //sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id); + //skypiax_signaling_write(tech_pvt, msg_to_skype); switch_mutex_unlock(globals.mutex); return 0; } @@ -1822,7 +1893,9 @@ int skypiax_answer(private_t * tech_pvt, char *id, char *value) } else if (!tech_pvt || !tech_pvt->skype_call_id) { ERRORA("No Call ID?\n", SKYPIAX_P_LOG); } else { - ERRORA("We're in a call now %s\n", SKYPIAX_P_LOG, tech_pvt->skype_call_id); + DEBUGA_SKYPE("We're in a call now (%s), let's refuse this one (%s)\n", SKYPIAX_P_LOG, tech_pvt->skype_call_id, id); + sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id); + skypiax_signaling_write(tech_pvt, msg_to_skype); } switch_mutex_unlock(globals.mutex); @@ -1858,6 +1931,8 @@ int skypiax_transfer(private_t * tech_pvt, char *id, char *value) if (found) { //tech_pvt->callid_number[0]='\0'; + //sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id); + //skypiax_signaling_write(tech_pvt, msg_to_skype); switch_mutex_unlock(globals.mutex); return 0; } @@ -1899,12 +1974,14 @@ int skypiax_transfer(private_t * tech_pvt, char *id, char *value) if (found) { //tech_pvt->callid_number[0]='\0'; + //sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id); + //skypiax_signaling_write(tech_pvt, msg_to_skype); switch_mutex_unlock(globals.mutex); return 0; } DEBUGA_SKYPE("NOT FOUND\n", SKYPIAX_P_LOG); - available_skypiax_interface = find_available_skypiax_interface(tech_pvt); + available_skypiax_interface = find_available_skypiax_interface_rr(tech_pvt); if (available_skypiax_interface) { /* there is a skypiax interface idle, let's transfer the call to it */ @@ -1922,14 +1999,15 @@ int skypiax_transfer(private_t * tech_pvt, char *id, char *value) } else { /* no skypiax interfaces idle, do nothing */ DEBUGA_SKYPE - ("Not answering the skype_call %s, because we are already in a skypiax call(%s) and no other skypiax interfaces are available OR another interface is answering this call\n", - SKYPIAX_P_LOG, tech_pvt->skype_call_id, id); - //sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id); + ("Not answering the skype_call %s, because we are already in a skypiax call(%s) and not transferring, because no other skypiax interfaces are available\n", + SKYPIAX_P_LOG, id, tech_pvt->skype_call_id); + sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id); + skypiax_signaling_write(tech_pvt, msg_to_skype); } switch_sleep(10000); DEBUGA_SKYPE - ("We (%s) have NOT answered a Skype RING on skype_call %s, because we are already in a skypiax call\n", - SKYPIAX_P_LOG, tech_pvt->skype_call_id, id); + ("We have NOT answered a Skype RING from skype_call %s, because we are already in a skypiax call (%s)\n", + SKYPIAX_P_LOG, id, tech_pvt->skype_call_id); switch_mutex_unlock(globals.mutex); } diff --git a/src/mod/endpoints/mod_skypiax/skypiax.h b/src/mod/endpoints/mod_skypiax/skypiax.h index 51f5f6e236..71086b2524 100644 --- a/src/mod/endpoints/mod_skypiax/skypiax.h +++ b/src/mod/endpoints/mod_skypiax/skypiax.h @@ -98,6 +98,8 @@ typedef enum { #define SKYPIAX_STATE_UP 5 #define SKYPIAX_STATE_RINGING 6 #define SKYPIAX_STATE_PRERING 7 +#define SKYPIAX_STATE_ERROR_DOUBLE_CALL 8 +#define SKYPIAX_STATE_SELECTED 9 /*********************************/ /* call flow from the device */ #define CALLFLOW_CALL_IDLE SKYPIAX_STATE_DOWN @@ -244,7 +246,6 @@ struct private_object { typedef struct private_object private_t; void *SWITCH_THREAD_FUNC skypiax_api_thread_func(switch_thread_t * thread, void *obj); -void skypiax_tech_init(private_t * tech_pvt, switch_core_session_t *session); int skypiax_audio_read(private_t * tech_pvt); int skypiax_audio_init(private_t * tech_pvt); int skypiax_signaling_write(private_t * tech_pvt, char *msg_to_skype); @@ -277,8 +278,9 @@ int skypiax_pipe_write(int pipe, short *buf, int howmany); #endif /* WIN32 */ int skypiax_close_socket(unsigned int fd); private_t *find_available_skypiax_interface(private_t * tech_pvt); -private_t *find_available_skypiax_interface_rr(void); +private_t *find_available_skypiax_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 skypiax_answer(private_t * tech_pvt, char *id, char *value); int skypiax_transfer(private_t * tech_pvt, char *id, char *value); +int skypiax_socket_create_and_bind(private_t * tech_pvt, int * which_port); diff --git a/src/mod/endpoints/mod_skypiax/skypiax_protocol.c b/src/mod/endpoints/mod_skypiax/skypiax_protocol.c index b62f146b72..f36340ef0a 100644 --- a/src/mod/endpoints/mod_skypiax/skypiax_protocol.c +++ b/src/mod/endpoints/mod_skypiax/skypiax_protocol.c @@ -25,6 +25,47 @@ XErrorHandler old_handler = 0; int xerror = 0; #endif /* WIN32 */ /*************************************/ + +int skypiax_socket_create_and_bind(private_t * tech_pvt, int * which_port) +{ + int s=-1; + struct sockaddr_in my_addr; + int start_port = 6001; + + memset(&my_addr, 0, sizeof(my_addr)); + my_addr.sin_family = AF_INET; + my_addr.sin_addr.s_addr = htonl(0x7f000001); /* use the localhost */ + + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + ERRORA("socket Error\n", SKYPIAX_P_LOG); + return -1; + } + + if(*which_port != 0) + start_port = *which_port; + + my_addr.sin_port = htons(start_port); + //tech_pvt->tcp_cli_port = start_port; + *which_port = start_port; + while (bind(s, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) < 0) { + DEBUGA_SKYPE("*which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPIAX_P_LOG, *which_port, tech_pvt->tcp_cli_port, tech_pvt->tcp_srv_port); + DEBUGA_SKYPE("EADDRINUSE=%d, bind errno=%d, error: %s\n", SKYPIAX_P_LOG, EADDRINUSE, errno, strerror(errno)); + start_port++; + my_addr.sin_port = htons(start_port); + *which_port = start_port; + DEBUGA_SKYPE("*which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPIAX_P_LOG, *which_port, tech_pvt->tcp_cli_port, tech_pvt->tcp_srv_port); + + if(start_port > 65000){ + ERRORA("NO MORE PORTS! *which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPIAX_P_LOG, *which_port, tech_pvt->tcp_cli_port, tech_pvt->tcp_srv_port); + return -1; + } + //usleep(100); + } + + DEBUGA_SKYPE("SUCCESS! *which_port=%d, tech_pvt->tcp_cli_port=%d, tech_pvt->tcp_srv_port=%d\n", SKYPIAX_P_LOG, *which_port, tech_pvt->tcp_cli_port, tech_pvt->tcp_srv_port); + return s; +} + int skypiax_signaling_read(private_t * tech_pvt) { char read_from_pipe[4096]; @@ -49,9 +90,9 @@ int skypiax_signaling_read(private_t * tech_pvt) if (read_from_pipe[i] == '\0') { - if (!strstr(message, "DURATION")) { + //if (!strstr(message, "DURATION")) { DEBUGA_SKYPE("READING: |||%s||| \n", SKYPIAX_P_LOG, message); - } + //} if (!strcasecmp(message, "ERROR 68")) { DEBUGA_SKYPE @@ -75,20 +116,48 @@ int skypiax_signaling_read(private_t * tech_pvt) tech_pvt->interface_state = SKYPIAX_STATE_DOWN; } } - skypiax_strncpy(message_2, message, sizeof(message) - 1); - buf = message; - stringp = &buf; - where = strsep(stringp, " "); - if (!where) { - WARNINGA("Skype MSG without spaces: %s\n", SKYPIAX_P_LOG, message); - } - if (!strcasecmp(message, "ERROR")) { - if (!strncasecmp(message, "ERROR 592 ALTER CALL", 19)) { - ERRORA("Skype got ERROR about TRANSFERRING, no problem: |||%s|||\n", SKYPIAX_P_LOG, message); + /* + if (!strncasecmp(message, "ERROR 96 CALL", 12) ) { + ERRORA("Skype got ERROR: |||%s|||, we are trying to use this interface to make or receive a call, but another call is half-active on this interface. We abort this attenpt and leave the previous one to continue.\n", SKYPIAX_P_LOG, message); + tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED; + DEBUGA_SKYPE("skype_call now is DOWN\n", SKYPIAX_P_LOG); + tech_pvt->skype_call_id[0] = '\0'; + + if (tech_pvt->interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) { + tech_pvt->interface_state = SKYPIAX_STATE_DOWN; + return CALLFLOW_INCOMING_HANGUP; } else { - DEBUGA_SKYPE("Skype got ERROR: |||%s|||\n", SKYPIAX_P_LOG, message); + tech_pvt->interface_state = SKYPIAX_STATE_DOWN; + } + } + */ + /* + if (!strncasecmp(message, "ERROR 99 CALL", 12) ) { + //TODO: let's kill the call + ERRORA("Skype got ERROR: |||%s|||, another call is active on this interface\n\n\n", SKYPIAX_P_LOG, message); + //tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED; + //DEBUGA_SKYPE("skype_call now is DOWN\n", SKYPIAX_P_LOG); + //tech_pvt->skype_call_id[0] = '\0'; + + tech_pvt->interface_state = SKYPIAX_STATE_ERROR_DOUBLE_CALL; + } + */ + + + if (!strncasecmp(message, "ERROR", 4)) { + if (!strncasecmp(message, "ERROR 96 CALL", 12) ) { + DEBUGA_SKYPE("Skype got ERROR: |||%s|||, we are trying to use this interface to make or receive a call, but another call is half-active on this interface. Let's the previous one to continue.\n", SKYPIAX_P_LOG, message); + } else if (!strncasecmp(message, "ERROR 99 CALL", 12) ) { + ERRORA("Skype got ERROR: |||%s|||, another call is active on this interface\n\n\n", SKYPIAX_P_LOG, message); + tech_pvt->interface_state = SKYPIAX_STATE_ERROR_DOUBLE_CALL; + } else if (!strncasecmp(message, "ERROR 592 ALTER CALL", 19)) { + ERRORA("Skype got ERROR about TRANSFERRING, no problem: |||%s|||\n", SKYPIAX_P_LOG, message); + } else if (!strncasecmp(message, "ERROR 559 CALL", 13)) { + DEBUGA_SKYPE("Skype got ERROR about a failed action (probably TRYING to HANGUP A CALL), no problem: |||%s|||\n", SKYPIAX_P_LOG, message); + } else { + ERRORA("Skype got ERROR: |||%s|||\n", SKYPIAX_P_LOG, message); tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED; - DEBUGA_SKYPE("skype_call now is DOWN\n", SKYPIAX_P_LOG); + ERRORA("skype_call now is DOWN\n", SKYPIAX_P_LOG); tech_pvt->skype_call_id[0] = '\0'; if (tech_pvt->interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) { @@ -99,6 +168,25 @@ int skypiax_signaling_read(private_t * tech_pvt) } } } + + + + + skypiax_strncpy(message_2, message, sizeof(message) - 1); + buf = message; + stringp = &buf; + where = strsep(stringp, " "); + if (!where) { + WARNINGA("Skype MSG without spaces: %s\n", SKYPIAX_P_LOG, message); + } + + + + + + + + if (!strcasecmp(message, "CURRENTUSERHANDLE")) { skypiax_strncpy(obj, where, sizeof(obj) - 1); where = strsep(stringp, " "); @@ -163,7 +251,8 @@ int skypiax_signaling_read(private_t * tech_pvt) //SKYPIAX_P_LOG, message, obj, id, prop, value, where ? where : "NULL"); if (!strcasecmp(prop, "PARTNER_HANDLE")) { - if (!strlen(tech_pvt->skype_call_id)) { + if (!strlen(tech_pvt->skype_call_id) || !strlen(tech_pvt->session_uuid_str)) { + //if (!strlen(tech_pvt->skype_call_id)) { /* we are NOT inside an active call */ DEBUGA_SKYPE("Call %s TRY ANSWER\n", SKYPIAX_P_LOG, id); skypiax_answer(tech_pvt, id, value); @@ -171,7 +260,7 @@ int skypiax_signaling_read(private_t * tech_pvt) /* we are inside an active call */ if (!strcasecmp(tech_pvt->skype_call_id, id)) { /* this is the call in which we are calling out */ - DEBUGA_SKYPE("Call %s NOTHING\n", SKYPIAX_P_LOG, id); + DEBUGA_SKYPE("Call %s DO NOTHING\n", SKYPIAX_P_LOG, id); } else { skypiax_sleep(400000); //0.4 seconds DEBUGA_SKYPE("Call %s TRY TRANSFER\n", SKYPIAX_P_LOG, id); @@ -208,12 +297,25 @@ int skypiax_signaling_read(private_t * tech_pvt) DEBUGA_SKYPE("We called a Skype contact and he answered us on skype_call: %s.\n", SKYPIAX_P_LOG, id); } } + + if (!strcasecmp(prop, "DURATION") && (tech_pvt->interface_state == SKYPIAX_STATE_ERROR_DOUBLE_CALL)) { + char msg_to_skype[1024]; + skypiax_strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1); + ERRORA("We are in a double call situation, trying to get out hanging up call id: %s.\n", SKYPIAX_P_LOG, id); + sprintf(msg_to_skype, "ALTER CALL %s HANGUP", id); + skypiax_signaling_write(tech_pvt, msg_to_skype); + skypiax_sleep(10000); + //return CALLFLOW_INCOMING_HANGUP; + } + if (!strcasecmp(prop, "STATUS")) { if (!strcasecmp(value, "RINGING")) { char msg_to_skype[1024]; - if (!strlen(tech_pvt->skype_call_id)) { + if ( (tech_pvt->interface_state != SKYPIAX_STATE_SELECTED && tech_pvt->interface_state != SKYPIAX_STATE_DIALING ) && (!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", SKYPIAX_P_LOG, id); sprintf(msg_to_skype, "GET CALL %s PARTNER_HANDLE", id); skypiax_signaling_write(tech_pvt, msg_to_skype); skypiax_sleep(10000); @@ -227,6 +329,7 @@ int skypiax_signaling_read(private_t * tech_pvt) DEBUGA_SKYPE("Our remote party in skype_call %s is RINGING\n", SKYPIAX_P_LOG, id); remote_party_is_ringing(tech_pvt); } else { + DEBUGA_SKYPE("We are in another call, but skype_call %s is RINGING on us, let's ask PARTNER_HANDLE, so maybe we'll TRANSFER\n", SKYPIAX_P_LOG, id); sprintf(msg_to_skype, "GET CALL %s PARTNER_HANDLE", id); skypiax_signaling_write(tech_pvt, msg_to_skype); skypiax_sleep(10000); @@ -237,7 +340,10 @@ int skypiax_signaling_read(private_t * tech_pvt) tech_pvt->skype_callflow = CALLFLOW_STATUS_EARLYMEDIA; tech_pvt->interface_state = SKYPIAX_STATE_DIALING; DEBUGA_SKYPE("Our remote party in skype_call %s is EARLYMEDIA\n", SKYPIAX_P_LOG, id); - start_audio_threads(tech_pvt); + if (start_audio_threads(tech_pvt)){ + ERRORA("start_audio_threads FAILED\n", SKYPIAX_P_LOG); + return CALLFLOW_INCOMING_HANGUP; + } skypiax_sleep(1000); sprintf(msg_to_skype, "ALTER CALL %s SET_INPUT PORT=\"%d\"", id, tech_pvt->tcp_cli_port); skypiax_signaling_write(tech_pvt, msg_to_skype); @@ -251,9 +357,9 @@ int skypiax_signaling_read(private_t * tech_pvt) //DEBUGA_SKYPE("skype_call %s now is DOWN\n", SKYPIAX_P_LOG, id); //usleep(150000);//150msec, let's give the TCP sockets time to timeout if (!strcasecmp(tech_pvt->skype_call_id, id)) { - tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED; + //tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED; DEBUGA_SKYPE("skype_call %s is MY call, now I'm going DOWN\n", SKYPIAX_P_LOG, id); - tech_pvt->skype_call_id[0] = '\0'; + //tech_pvt->skype_call_id[0] = '\0'; if (tech_pvt->interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) { //tech_pvt->interface_state = SKYPIAX_STATE_DOWN; return CALLFLOW_INCOMING_HANGUP; @@ -311,6 +417,9 @@ int skypiax_signaling_read(private_t * tech_pvt) } else if (!strcasecmp(value, "INPROGRESS")) { char msg_to_skype[1024]; + if (!strlen(tech_pvt->session_uuid_str)) { + DEBUGA_SKYPE("no tech_pvt->session_uuid_str\n", SKYPIAX_P_LOG); + } if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) { if (!strlen(tech_pvt->session_uuid_str) || !strlen(tech_pvt->skype_call_id) || !strcasecmp(tech_pvt->skype_call_id, id)) { @@ -320,7 +429,11 @@ int skypiax_signaling_read(private_t * tech_pvt) if (tech_pvt->skype_callflow != CALLFLOW_STATUS_EARLYMEDIA) { tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS; tech_pvt->interface_state = SKYPIAX_STATE_UP; - start_audio_threads(tech_pvt); + + if (start_audio_threads(tech_pvt)){ + ERRORA("start_audio_threads FAILED\n", SKYPIAX_P_LOG); + return CALLFLOW_INCOMING_HANGUP; + } skypiax_sleep(1000); //FIXME sprintf(msg_to_skype, "ALTER CALL %s SET_INPUT PORT=\"%d\"", id, tech_pvt->tcp_cli_port); skypiax_signaling_write(tech_pvt, msg_to_skype); @@ -330,7 +443,7 @@ int skypiax_signaling_read(private_t * tech_pvt) } tech_pvt->skype_callflow = SKYPIAX_STATE_UP; if (!strlen(tech_pvt->session_uuid_str)) { - DEBUGA_SKYPE("New Inbound Channel!\n", SKYPIAX_P_LOG); + DEBUGA_SKYPE("New Inbound Channel!\n\n\n\n", SKYPIAX_P_LOG); new_inbound_channel(tech_pvt); } else { DEBUGA_SKYPE("Outbound Channel Answered!\n", SKYPIAX_P_LOG); @@ -413,13 +526,14 @@ void *skypiax_do_tcp_srv_thread_func(void *obj) unsigned int fd; short srv_in[SAMPLES_PER_FRAME]; short srv_out[SAMPLES_PER_FRAME / 2]; - struct sockaddr_in my_addr; + //struct sockaddr_in my_addr; struct sockaddr_in remote_addr; //int exit = 0; unsigned int kill_cli_size; short kill_cli_buff[SAMPLES_PER_FRAME]; short totalbuf[SAMPLES_PER_FRAME]; +#ifdef NOTDEF memset(&my_addr, 0, sizeof(my_addr)); my_addr.sin_family = AF_INET; my_addr.sin_addr.s_addr = htonl(0x7f000001); /* use the localhost */ @@ -427,11 +541,21 @@ void *skypiax_do_tcp_srv_thread_func(void *obj) if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { ERRORA("socket Error\n", SKYPIAX_P_LOG); + tech_pvt->tcp_srv_thread = NULL; return NULL; } if (bind(s, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) < 0) { - ERRORA("bind Error\n", SKYPIAX_P_LOG); + ERRORA("bind error: %s\n", SKYPIAX_P_LOG, strerror(errno)); + tech_pvt->tcp_srv_thread = NULL; + return NULL; + } +#endif //NOTDEF + + s = skypiax_socket_create_and_bind(tech_pvt, &tech_pvt->tcp_srv_port); + if(s < 0) + { + ERRORA("skypiax_socket_create_and_bind error!\n", SKYPIAX_P_LOG); return NULL; } DEBUGA_SKYPE("started tcp_srv_thread thread.\n", SKYPIAX_P_LOG); @@ -546,7 +670,7 @@ void *skypiax_do_tcp_srv_thread_func(void *obj) } else if (len == 0) { skypiax_sleep(1000); } else { - ERRORA("len=%d, expected 320\n", SKYPIAX_P_LOG, len); + DEBUGA_SKYPE("len=%d, expected 320\n", SKYPIAX_P_LOG, len); } } else { @@ -578,6 +702,7 @@ void *skypiax_do_tcp_srv_thread_func(void *obj) DEBUGA_SKYPE("incoming audio server (I am it) EXITING\n", SKYPIAX_P_LOG); skypiax_close_socket(s); + tech_pvt->tcp_srv_thread = NULL; return NULL; } @@ -585,7 +710,7 @@ void *skypiax_do_tcp_cli_thread_func(void *obj) { private_t *tech_pvt = obj; int s; - struct sockaddr_in my_addr; + //struct sockaddr_in my_addr; struct sockaddr_in remote_addr; unsigned int got; unsigned int len; @@ -600,6 +725,7 @@ void *skypiax_do_tcp_cli_thread_func(void *obj) unsigned int sin_size; #endif /* WIN32 */ +#ifdef NOTDEF memset(&my_addr, 0, sizeof(my_addr)); my_addr.sin_family = AF_INET; my_addr.sin_addr.s_addr = htonl(0x7f000001); /* use the localhost */ @@ -607,14 +733,29 @@ void *skypiax_do_tcp_cli_thread_func(void *obj) if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { ERRORA("socket Error\n", SKYPIAX_P_LOG); + tech_pvt->tcp_cli_thread = NULL; return NULL; } if (bind(s, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) < 0) { - ERRORA("bind Error\n", SKYPIAX_P_LOG); + //ERRORA("bind Error\n", SKYPIAX_P_LOG); + ERRORA("bind error: %s\n", SKYPIAX_P_LOG, strerror(errno)); skypiax_close_socket(s); + tech_pvt->tcp_cli_thread = NULL; return NULL; } + +#endif // NOTDEF + + s = skypiax_socket_create_and_bind(tech_pvt, &tech_pvt->tcp_cli_port); + if(s < 0) + { + ERRORA("skypiax_socket_create_and_bind error!\n", SKYPIAX_P_LOG); + return NULL; + } + + + DEBUGA_SKYPE("started tcp_cli_thread thread.\n", SKYPIAX_P_LOG); listen(s, 6); @@ -764,6 +905,7 @@ void *skypiax_do_tcp_cli_thread_func(void *obj) DEBUGA_SKYPE("outbound audio server (I am it) EXITING\n", SKYPIAX_P_LOG); skypiax_close_socket(s); + tech_pvt->tcp_cli_thread = NULL; return NULL; }