From 80e2633bb784842abf76ff9f6ed502288421f16b Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Aug 2013 20:34:29 +0500 Subject: [PATCH 1/5] add mutex in media_engine to prevent double read in video thread --- src/switch_core_media.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/switch_core_media.c b/src/switch_core_media.c index d0acc32564..b7c57a5abe 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -156,6 +156,7 @@ typedef struct switch_rtp_engine_s { struct media_helper mh; switch_thread_t *media_thread; + switch_mutex_t *read_mutex; } switch_rtp_engine_t; @@ -1224,6 +1225,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session switch_assert(engine->rtp_session != NULL); engine->read_frame.datalen = 0; + if (switch_mutex_trylock(engine->read_mutex) != SWITCH_STATUS_SUCCESS) { + /* return CNG for now */ + *frame = &engine->read_frame; + switch_set_flag((*frame), SFF_CNG); + (*frame)->datalen = engine->read_impl.encoded_bytes_per_packet; + memset((*frame)->data, 0, (*frame)->datalen); + return SWITCH_STATUS_SUCCESS; + } + while (smh->media_flags[SCMF_RUNNING] && engine->read_frame.datalen == 0) { engine->read_frame.flags = SFF_NONE; @@ -1239,13 +1249,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session (*frame)->datalen = engine->read_impl.encoded_bytes_per_packet; memset((*frame)->data, 0, (*frame)->datalen); switch_channel_execute_on(session->channel, "execute_on_media_timeout"); - return SWITCH_STATUS_SUCCESS; + switch_goto_status(SWITCH_STATUS_SUCCESS, end); } switch_channel_hangup(session->channel, SWITCH_CAUSE_MEDIA_TIMEOUT); } - return status; + goto end; } /* Try to read an RTCP frame, if successful raise an event */ @@ -1322,7 +1332,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session /* Fast PASS! */ if (switch_test_flag((&engine->read_frame), SFF_PROXY_PACKET)) { *frame = &engine->read_frame; - return SWITCH_STATUS_SUCCESS; + switch_goto_status(SWITCH_STATUS_SUCCESS, end); } if (switch_rtp_has_dtmf(engine->rtp_session)) { @@ -1338,7 +1348,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session if (!switch_test_flag((&engine->read_frame), SFF_CNG)) { if (!engine->read_codec.implementation || !switch_core_codec_ready(&engine->read_codec)) { *frame = NULL; - return SWITCH_STATUS_GENERR; + switch_goto_status(SWITCH_STATUS_GENERR, end); } /* check for timing or codec issues */ @@ -1475,7 +1485,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session if (switch_rtp_ready(engine->rtp_session)) { if (switch_core_media_set_codec(session, 2, 0) != SWITCH_STATUS_SUCCESS) { *frame = NULL; - return SWITCH_STATUS_GENERR; + switch_goto_status(SWITCH_STATUS_GENERR, end); } if ((val = switch_channel_get_variable(session->channel, "rtp_timeout_sec"))) { @@ -1516,7 +1526,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session switch_set_flag((*frame), SFF_CNG); (*frame)->datalen = engine->read_impl.encoded_bytes_per_packet; memset((*frame)->data, 0, (*frame)->datalen); - return SWITCH_STATUS_SUCCESS; + switch_goto_status(SWITCH_STATUS_SUCCESS, end); } } @@ -1541,7 +1551,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session *frame = &engine->read_frame; - return SWITCH_STATUS_SUCCESS; + status = SWITCH_STATUS_SUCCESS; + + end: + + switch_mutex_unlock(engine->read_mutex); + + return status; } //? @@ -4164,6 +4180,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi uint8_t inb = switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_INBOUND; const char *ssrc; + switch_mutex_init(&a_engine->read_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); + //switch_core_media_set_rtp_session(session, SWITCH_MEDIA_TYPE_AUDIO, a_engine->rtp_session); if ((ssrc = switch_channel_get_variable(session->channel, "rtp_use_ssrc"))) { @@ -4623,6 +4641,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi switch_thread_cond_create(&v_engine->mh.cond, pool); switch_mutex_init(&v_engine->mh.cond_mutex, SWITCH_MUTEX_NESTED, pool); + switch_mutex_init(&v_engine->read_mutex, SWITCH_MUTEX_NESTED, pool); switch_thread_create(&v_engine->media_thread, thd_attr, video_helper_thread, &v_engine->mh, switch_core_session_get_pool(session)); } From d35db852a8bcc4fb10e7a8486046aabd45a7f9b2 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Aug 2013 12:17:00 -0400 Subject: [PATCH 2/5] follow up to last commit --- src/include/switch_core.h | 2 ++ .../mod_conference/mod_conference.c | 3 +++ src/switch_core_media.c | 9 ++++++++- src/switch_core_session.c | 19 ++++++++----------- src/switch_core_state_machine.c | 2 ++ src/switch_ivr_bridge.c | 7 ++++--- 6 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index dfa1d39d7c..880cf9b893 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -1015,6 +1015,8 @@ SWITCH_DECLARE(switch_app_log_t *) switch_core_session_get_app_log(_In_ switch_c */ SWITCH_DECLARE(switch_status_t) switch_core_session_exec(_In_ switch_core_session_t *session, _In_ const switch_application_interface_t *application_interface, _In_opt_z_ const char *arg); + +SWITCH_DECLARE(void) switch_core_session_video_reset(switch_core_session_t *session); /*! \brief Execute an application on a session \param session the current session diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 99b992befd..698b2079bd 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -7472,6 +7472,8 @@ SWITCH_STANDARD_APP(conference_function) switch_channel_set_app_flag_key("conf_silent", channel, CONF_SILENT_REQ); } + switch_core_session_video_reset(session); + switch_channel_set_flag(channel, CF_CONFERENCE); if (switch_channel_answer(channel) != SWITCH_STATUS_SUCCESS) { @@ -8028,6 +8030,7 @@ SWITCH_STANDARD_APP(conference_function) switch_channel_clear_flag(channel, CF_CONFERENCE); + switch_core_session_video_reset(session); } /* Create a thread for the conference and launch it */ diff --git a/src/switch_core_media.c b/src/switch_core_media.c index b7c57a5abe..b18ec859e8 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -1225,12 +1225,19 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_frame(switch_core_session switch_assert(engine->rtp_session != NULL); engine->read_frame.datalen = 0; + if (!switch_channel_up_nosig(session->channel) || !switch_rtp_ready(engine->rtp_session) || switch_channel_test_flag(session->channel, CF_NOT_READY)) { + return SWITCH_STATUS_FALSE; + } + if (switch_mutex_trylock(engine->read_mutex) != SWITCH_STATUS_SUCCESS) { - /* return CNG for now */ + /* return CNG, another thread is already reading */ *frame = &engine->read_frame; switch_set_flag((*frame), SFF_CNG); (*frame)->datalen = engine->read_impl.encoded_bytes_per_packet; memset((*frame)->data, 0, (*frame)->datalen); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s is already being read for %s\n", + switch_channel_get_name(session->channel), type2str(type)); + switch_yield(10000); return SWITCH_STATUS_SUCCESS; } diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 0768feed15..a67359d677 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -2521,6 +2521,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_async(sw return SWITCH_STATUS_FALSE; } +SWITCH_DECLARE(void) switch_core_session_video_reset(switch_core_session_t *session) +{ + if (switch_channel_test_flag(session->channel, CF_VIDEO)) { + switch_channel_set_flag(session->channel, CF_VIDEO_ECHO); + switch_channel_clear_flag(session->channel, CF_VIDEO_PASSIVE); + switch_core_session_refresh_video(session); + } +} SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flags(switch_core_session_t *session, const char *app, const char *arg, int32_t *flags) @@ -2736,19 +2744,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_exec(switch_core_session_t * msg.string_array_arg[1] = expanded; switch_core_session_receive_message(session, &msg); - if (switch_channel_test_flag(channel, CF_VIDEO)) { - switch_channel_set_flag(channel, CF_VIDEO_ECHO); - switch_channel_clear_flag(channel, CF_VIDEO_PASSIVE); - switch_core_session_refresh_video(session); - } - application_interface->application_function(session, expanded); - if (switch_channel_test_flag(channel, CF_VIDEO)) { - switch_channel_set_flag(channel, CF_VIDEO_ECHO); - switch_channel_clear_flag(channel, CF_VIDEO_PASSIVE); - switch_core_session_refresh_video(session); - } if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE) == SWITCH_STATUS_SUCCESS) { const char *resp = switch_channel_get_variable(session->channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE); switch_channel_event_set_data(session->channel, event); diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index 56811a1e75..5926e52586 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -216,6 +216,8 @@ static void switch_core_standard_on_execute(switch_core_session_t *session) top: switch_channel_clear_flag(session->channel, CF_RESET); + + switch_core_session_video_reset(session); if ((extension = switch_channel_get_caller_extension(session->channel)) == 0) { switch_channel_hangup(session->channel, SWITCH_CAUSE_NORMAL_CLEARING); diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index f9b22f8a4f..e0d005aec9 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -63,7 +63,7 @@ static void *SWITCH_THREAD_FUNC video_bridge_thread(switch_thread_t *thread, voi if (!switch_stristr("loopback", source) && !switch_stristr("loopback", b_source)) { switch_channel_set_flag(channel, CF_VIDEO_PASSIVE); - switch_channel_set_flag(b_channel, CF_VIDEO_PASSIVE); + //switch_channel_set_flag(b_channel, CF_VIDEO_PASSIVE); } switch_core_session_refresh_video(vh->session_a); @@ -94,7 +94,7 @@ static void *SWITCH_THREAD_FUNC video_bridge_thread(switch_thread_t *thread, voi } switch_channel_clear_flag(channel, CF_VIDEO_PASSIVE); - switch_channel_clear_flag(b_channel, CF_VIDEO_PASSIVE); + //switch_channel_clear_flag(b_channel, CF_VIDEO_PASSIVE); switch_core_session_kill_channel(vh->session_b, SWITCH_SIG_BREAK); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(vh->session_a), SWITCH_LOG_DEBUG, "%s video thread ended.\n", switch_channel_get_name(channel)); @@ -624,7 +624,8 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj) if (vid_thread) { switch_status_t st; - if (vh.up) { + if (vh.up == 1) { + vh.up = -1; switch_core_session_kill_channel(session_a, SWITCH_SIG_BREAK); switch_core_session_kill_channel(session_b, SWITCH_SIG_BREAK); } From c21f65ac5519d26f12c969e26d8d3e009538e6df Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Sat, 17 Aug 2013 02:13:49 +0500 Subject: [PATCH 3/5] FS-5708 --resolve --- src/switch_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_utils.c b/src/switch_utils.c index a11f908dce..8b5fc8e3c9 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -1273,7 +1273,7 @@ static int get_netmask(struct sockaddr_in *me, int *mask) struct sockaddr_in *s = (struct sockaddr_in *) i->ifa_addr; struct sockaddr_in *m = (struct sockaddr_in *) i->ifa_netmask; - if (s && m && s->sin_addr.s_addr == me->sin_addr.s_addr) { + if (s && m && addr->ifa_addr->sa_family == AF_INET && s->sin_addr && s->sin_addr.s_addr == me->sin_addr.s_addr) { *mask = m->sin_addr.s_addr; freeifaddrs(ifaddrs); return 0; From 8e45f23d028f6c3fe375a2dc307b6e66f99e39bb Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Sat, 17 Aug 2013 02:16:28 +0500 Subject: [PATCH 4/5] FS-5709 --resolve --- src/include/switch_console.h | 1 + src/include/switch_utils.h | 15 ++++- .../applications/mod_commands/mod_commands.c | 47 ++++++++++++++++ src/mod/endpoints/mod_sofia/sofia.c | 26 +++++++++ src/switch_console.c | 46 ++++++++++++++++ src/switch_utils.c | 55 +++++++++++++++++++ 6 files changed, 189 insertions(+), 1 deletion(-) diff --git a/src/include/switch_console.h b/src/include/switch_console.h index e6f6cf476e..73410bd248 100644 --- a/src/include/switch_console.h +++ b/src/include/switch_console.h @@ -83,6 +83,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_add_complete_func(const char *nam SWITCH_DECLARE(switch_status_t) switch_console_del_complete_func(const char *name); SWITCH_DECLARE(switch_status_t) switch_console_run_complete_func(const char *func, const char *line, const char *last_word, switch_console_callback_match_t **matches); +SWITCH_DECLARE(void) switch_console_push_match_unique(switch_console_callback_match_t **matches, const char *new_val); SWITCH_DECLARE(void) switch_console_push_match(switch_console_callback_match_t **matches, const char *new_val); SWITCH_DECLARE(void) switch_console_free_matches(switch_console_callback_match_t **matches); SWITCH_DECLARE(unsigned char) switch_console_complete(const char *line, const char *last_word, diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h index 40630d8c9f..f4aa3d7f28 100644 --- a/src/include/switch_utils.h +++ b/src/include/switch_utils.h @@ -467,14 +467,27 @@ SWITCH_DECLARE(switch_status_t) switch_resolve_host(const char *host, char *buf, /*! \brief find local ip of the box - \param buf the buffer to write the ip adress found into + \param buf the buffer to write the ip address found into \param len the length of the buf + \param mask the CIDR found (AF_INET only) \param family the address family to return (AF_INET or AF_INET6) \return SWITCH_STATUS_SUCCESSS for success, otherwise failure */ SWITCH_DECLARE(switch_status_t) switch_find_local_ip(_Out_opt_bytecapcount_(len) char *buf, _In_ int len, _In_opt_ int *mask, _In_ int family); +/*! + \brief find primary ip of the specified interface + \param buf the buffer to write the ip address found into + \param len the length of the buf + \param mask the CIDR found (AF_INET only) + \param ifname interface name to check + \param family the address family to return (AF_INET or AF_INET6) + \return SWITCH_STATUS_SUCCESSS for success, otherwise failure +*/ +SWITCH_DECLARE(switch_status_t) switch_find_interface_ip(_Out_opt_bytecapcount_(len) + char *buf, _In_ int len, _In_opt_ int *mask, _In_ const char *ifname, _In_ int family); + /*! \brief find the char representation of an ip adress \param buf the buffer to write the ip adress found into diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index fc74c3dd65..abc0aace9a 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -6028,6 +6028,49 @@ SWITCH_STANDARD_API(file_exists_function) return SWITCH_STATUS_SUCCESS; } +#define INTERFACE_IP_SYNTAX "[auto|ipv4|ipv6] " +SWITCH_STANDARD_API(interface_ip_function) +{ + char *mydata = NULL, *argv[3] = { 0 }; + int argc = 0; + char addr[INET6_ADDRSTRLEN]; + + if (!zstr(cmd)) { + mydata = strdup(cmd); + switch_assert(mydata); + argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + } + + if (argc < 2) { + stream->write_function(stream, "USAGE: interface_ip %s\n", INTERFACE_IP_SYNTAX); + goto end; + } + + if (!strcasecmp(argv[0], "ipv4")) { + if (switch_find_interface_ip(addr, sizeof(addr), NULL, argv[1], AF_INET) == SWITCH_STATUS_SUCCESS) { + stream->write_function(stream, "%s", addr); + } + } + else if (!strcasecmp(argv[0], "ipv6")) { + if (switch_find_interface_ip(addr, sizeof(addr), NULL, argv[1], AF_INET6) == SWITCH_STATUS_SUCCESS) { + stream->write_function(stream, "%s", addr); + } + } + else if (!strcasecmp(argv[0], "auto")) { + if (switch_find_interface_ip(addr, sizeof(addr), NULL, argv[1], AF_UNSPEC) == SWITCH_STATUS_SUCCESS) { + stream->write_function(stream, "%s", addr); + } + } + else { + stream->write_function(stream, "USAGE: interface_ip %s\n", INTERFACE_IP_SYNTAX); + } + +end: + switch_safe_free(mydata); + + return SWITCH_STATUS_SUCCESS; +} + SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) { switch_api_interface_t *commands_api_interface; @@ -6065,6 +6108,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) SWITCH_ADD_API(commands_api_interface, "help", "Show help for all the api commands", help_function, ""); SWITCH_ADD_API(commands_api_interface, "host_lookup", "Lookup host", host_lookup_function, ""); SWITCH_ADD_API(commands_api_interface, "hostname", "Return the system hostname", hostname_api_function, ""); + SWITCH_ADD_API(commands_api_interface, "interface_ip", "Return the primary IP of an interface", interface_ip_function, INTERFACE_IP_SYNTAX); SWITCH_ADD_API(commands_api_interface, "switchname", "Return the switch name", switchname_api_function, ""); SWITCH_ADD_API(commands_api_interface, "hupall", "hupall", hupall_api_function, " [ ]"); SWITCH_ADD_API(commands_api_interface, "in_group", "Determine if a user is in a group", in_group_function, "[@] "); @@ -6217,6 +6261,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) switch_console_set_complete("add fsctl flush_db_handles"); switch_console_set_complete("add fsctl min_idle_cpu"); switch_console_set_complete("add fsctl send_sighup"); + switch_console_set_complete("add interface_ip auto ::console::list_interfaces"); + switch_console_set_complete("add interface_ip ipv4 ::console::list_interfaces"); + switch_console_set_complete("add interface_ip ipv6 ::console::list_interfaces"); switch_console_set_complete("add load ::console::list_available_modules"); switch_console_set_complete("add nat_map reinit"); switch_console_set_complete("add nat_map republish"); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 40c8bc370d..b399284337 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -4104,9 +4104,22 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name) } } else if (!strcasecmp(var, "rtp-ip")) { char *ip = mod_sofia_globals.guess_ip; + char buf[64]; if (!strcmp(val, "0.0.0.0")) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid IP 0.0.0.0 replaced with %s\n", mod_sofia_globals.guess_ip); + } else if (!strncasecmp(val, "interface:", 10)) { + char *ifname = val+10; + int family = AF_UNSPEC; + if (!strncasecmp(ifname, "auto/", 5)) { ifname += 5; family = AF_UNSPEC; } + if (!strncasecmp(ifname, "ipv4/", 5)) { ifname += 5; family = AF_INET; } + if (!strncasecmp(ifname, "ipv6/", 5)) { ifname += 5; family = AF_INET6; } + if (switch_find_interface_ip(buf, sizeof(buf), NULL, ifname, family) == SWITCH_STATUS_SUCCESS) { + ip = buf; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Using %s IP for interface %s for rtp-ip\n", ip, val+10); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown IP for interface %s for rtp-ip\n", val+10); + } } else { ip = strcasecmp(val, "auto") ? val : mod_sofia_globals.guess_ip; } @@ -4117,9 +4130,22 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name) } } else if (!strcasecmp(var, "sip-ip")) { char *ip = mod_sofia_globals.guess_ip; + char buf[64]; if (!strcmp(val, "0.0.0.0")) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid IP 0.0.0.0 replaced with %s\n", mod_sofia_globals.guess_ip); + } else if (!strncasecmp(val, "interface:", 10)) { + char *ifname = val+10; + int family = AF_UNSPEC; + if (!strncasecmp(ifname, "auto/", 5)) { ifname += 5; family = AF_UNSPEC; } + if (!strncasecmp(ifname, "ipv4/", 5)) { ifname += 5; family = AF_INET; } + if (!strncasecmp(ifname, "ipv6/", 5)) { ifname += 5; family = AF_INET6; } + if (switch_find_interface_ip(buf, sizeof(buf), NULL, ifname, family) == SWITCH_STATUS_SUCCESS) { + ip = buf; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Using %s IP for interface %s for sip-ip\n", ip, val+10); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown IP for interface %s for sip-ip\n", val+10); + } } else { ip = strcasecmp(val, "auto") ? val : mod_sofia_globals.guess_ip; } diff --git a/src/switch_console.c b/src/switch_console.c index b1e2c8e271..b2c003a6c6 100644 --- a/src/switch_console.c +++ b/src/switch_console.c @@ -33,6 +33,7 @@ #include #include #include +#include #define CMD_BUFLEN 1024 #ifdef SWITCH_HAVE_LIBEDIT @@ -619,6 +620,36 @@ SWITCH_DECLARE_NONSTD(switch_status_t) switch_console_list_loaded_modules(const return SWITCH_STATUS_FALSE; } +#ifdef HAVE_GETIFADDRS +#include +#include +SWITCH_DECLARE_NONSTD(switch_status_t) switch_console_list_interfaces(const char *line, const char *cursor, switch_console_callback_match_t **matches) +{ + struct match_helper h = { 0 }; + struct ifaddrs *addrs, *addr; + + getifaddrs(&addrs); + for(addr = addrs; addr; addr = addr->ifa_next) { + if (addr->ifa_flags & IFF_UP) { + switch_console_push_match_unique(&h.my_matches, addr->ifa_name); + } + } + freeifaddrs(addrs); + + if (h.my_matches) { + *matches = h.my_matches; + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_FALSE; +} +#else +SWITCH_DECLARE_NONSTD(switch_status_t) switch_console_list_interfaces(const char *line, const char *cursor, switch_console_callback_match_t **matches) +{ + return SWITCH_STATUS_FALSE; +} +#endif + static int uuid_callback(void *pArg, int argc, char **argv, char **columnNames) { struct match_helper *h = (struct match_helper *) pArg; @@ -1631,6 +1662,7 @@ SWITCH_DECLARE(switch_status_t) switch_console_init(switch_memory_pool_t *pool) switch_core_hash_init(&globals.func_hash, pool); switch_console_add_complete_func("::console::list_available_modules", (switch_console_complete_callback_t) switch_console_list_available_modules); switch_console_add_complete_func("::console::list_loaded_modules", (switch_console_complete_callback_t) switch_console_list_loaded_modules); + switch_console_add_complete_func("::console::list_interfaces", (switch_console_complete_callback_t) switch_console_list_interfaces); switch_console_add_complete_func("::console::list_uuid", (switch_console_complete_callback_t) switch_console_list_uuid); return SWITCH_STATUS_SUCCESS; } @@ -1741,6 +1773,20 @@ SWITCH_DECLARE(void) switch_console_sort_matches(switch_console_callback_match_t } } +SWITCH_DECLARE(void) switch_console_push_match_unique(switch_console_callback_match_t **matches, const char *new_val) +{ + /* Ignore the entry if it is already in the list */ + if (*matches) { + switch_console_callback_match_node_t *node; + + for(node = (*matches)->head; node; node = node->next) { + if (!strcasecmp(node->val, new_val)) return; + } + } + + switch_console_push_match(matches, new_val); +} + SWITCH_DECLARE(void) switch_console_push_match(switch_console_callback_match_t **matches, const char *new_val) { switch_console_callback_match_node_t *match; diff --git a/src/switch_utils.c b/src/switch_utils.c index 8b5fc8e3c9..bc3a9364e3 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -1580,6 +1580,61 @@ SWITCH_DECLARE(switch_status_t) switch_find_local_ip(char *buf, int len, int *ma return status; } +#ifdef HAVE_GETIFADDRS +# include +# include +#endif +SWITCH_DECLARE(switch_status_t) switch_find_interface_ip(char *buf, int len, int *mask, const char *ifname, int family) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + +#ifdef HAVE_GETIFADDRS + + struct ifaddrs *addrs, *addr; + + getifaddrs(&addrs); + for(addr = addrs; addr; addr = addr->ifa_next) + { + if (!(addr->ifa_flags & IFF_UP)) continue; // Address is not UP + if (!addr->ifa_addr) continue; // No address set + if (!addr->ifa_netmask) continue; // No netmask set + if (family != AF_UNSPEC && addr->ifa_addr->sa_family != family) continue; // Not the address family we're looking for + if (strcmp(addr->ifa_name, ifname)) continue; // Not the interface we're looking for + + switch(addr->ifa_addr->sa_family) { + case AF_INET: + inet_ntop(AF_INET, &( ((struct sockaddr_in*)(addr->ifa_addr))->sin_addr ), buf, len - 1); + break; + case AF_INET6: + inet_ntop(AF_INET6, &( ((struct sockaddr_in6*)(addr->ifa_addr))->sin6_addr ), buf, len - 1); + break; + default: + continue; + } + + if (mask && addr->ifa_netmask->sa_family == AF_INET) { + *mask = ((struct sockaddr_in*)(addr->ifa_addr))->sin_addr.s_addr; + } + + status = SWITCH_STATUS_SUCCESS; + break; + } + freeifaddrs(addrs); + +#elif defined(__linux__) + + // TODO Not implemented, contributions welcome. + +#elif defined(WIN32) + + // TODO Not implemented, contributions welcome. + +#endif + + return status; +} + + SWITCH_DECLARE(switch_time_t) switch_str_time(const char *in) { switch_time_exp_t tm = { 0 }; From 1facd34bde5986e521abbd28509edd79855c7c6a Mon Sep 17 00:00:00 2001 From: Ken Rice Date: Fri, 16 Aug 2013 17:53:12 -0500 Subject: [PATCH 5/5] Revert "FS-5708 ... problems with build on this one This reverts commit c21f65ac5519d26f12c969e26d8d3e009538e6df. --- src/switch_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_utils.c b/src/switch_utils.c index bc3a9364e3..1412dd41fe 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -1273,7 +1273,7 @@ static int get_netmask(struct sockaddr_in *me, int *mask) struct sockaddr_in *s = (struct sockaddr_in *) i->ifa_addr; struct sockaddr_in *m = (struct sockaddr_in *) i->ifa_netmask; - if (s && m && addr->ifa_addr->sa_family == AF_INET && s->sin_addr && s->sin_addr.s_addr == me->sin_addr.s_addr) { + if (s && m && s->sin_addr.s_addr == me->sin_addr.s_addr) { *mask = m->sin_addr.s_addr; freeifaddrs(ifaddrs); return 0;