[commit] r10265 - freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax
Author: gmaruzz Date: Thu Nov 6 05:00:22 2008 New Revision: 10265 Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax.c Log: skypiax: let's begin to parse nested configuration, eg: multiple interfaces Modified: freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax.c ============================================================================== --- freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax.c (original) +++ freeswitch/branches/gmaruzz/src/mod/endpoints/mod_skypiax/mod_skypiax.c Thu Nov 6 05:00:22 2008 @@ -1,3 +1,5 @@ +#undef MOD_OPENZAP +#ifdef MOD_OPENZAP /* * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com> @@ -2199,3 +2201,820 @@ * For VIM: * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab: */ +#endif /* MOD_OPENZAP */ + +#define MOD_SKYPIAX +#ifdef MOD_SKYPIAX +#include <switch.h> + +SWITCH_MODULE_LOAD_FUNCTION(mod_skypiax_load); +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skypiax_shutdown); +//SWITCH_MODULE_RUNTIME_FUNCTION(mod_skypiax_runtime); +SWITCH_MODULE_DEFINITION(mod_skypiax, mod_skypiax_load, mod_skypiax_shutdown, NULL); //mod_skypiax_runtime); + + +switch_endpoint_interface_t *skypiax_endpoint_interface; +static switch_memory_pool_t *module_pool = NULL; +static int running = 1; + + +typedef enum { + TFLAG_IO = (1 << 0), + TFLAG_INBOUND = (1 << 1), + TFLAG_OUTBOUND = (1 << 2), + TFLAG_DTMF = (1 << 3), + TFLAG_VOICE = (1 << 4), + TFLAG_HANGUP = (1 << 5), + TFLAG_LINEAR = (1 << 6), + TFLAG_CODEC = (1 << 7), + TFLAG_BREAK = (1 << 8) +} TFLAGS; + +typedef enum { + GFLAG_MY_CODEC_PREFS = (1 << 0) +} GFLAGS; + + +static struct { + int debug; + char *ip; + int port; + char *dialplan; + char *codec_string; + char *codec_order[SWITCH_MAX_CODECS]; + int codec_order_last; + char *codec_rates_string; + char *codec_rates[SWITCH_MAX_CODECS]; + int codec_rates_last; + unsigned int flags; + int fd; + int calls; + char hold_music[256]; + switch_mutex_t *mutex; + //analog_option_t analog_options; +} globals; + +struct private_object { + unsigned int flags; + switch_codec_t read_codec; + switch_codec_t write_codec; + switch_frame_t read_frame; + unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; + switch_core_session_t *session; + switch_caller_profile_t *caller_profile; + switch_mutex_t *mutex; + switch_mutex_t *flag_mutex; + //switch_thread_cond_t *cond; +}; + +typedef struct private_object private_t; + + +SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan); +SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_string, globals.codec_string); +SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_rates_string, globals.codec_rates_string); +SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_ip, globals.ip); + + + +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_routing(switch_core_session_t *session); +static switch_status_t channel_on_exchange_media(switch_core_session_t *session); +static switch_status_t channel_on_soft_execute(switch_core_session_t *session); +static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, + switch_caller_profile_t *outbound_profile, + switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags); +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 void tech_init(private_t *tech_pvt, switch_core_session_t *session) +{ + 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); + tech_pvt->session = session; +} + +/* + State methods they get called when the state changes to the specific state + returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next + so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it. +*/ +static switch_status_t channel_on_init(switch_core_session_t *session) +{ + switch_channel_t *channel; + private_t *tech_pvt = NULL; + + tech_pvt = switch_core_session_get_private(session); + assert(tech_pvt != NULL); + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + switch_set_flag_locked(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 + 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); + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t channel_on_routing(switch_core_session_t *session) +{ + switch_channel_t *channel = NULL; + private_t *tech_pvt = NULL; + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + tech_pvt = switch_core_session_get_private(session); + assert(tech_pvt != NULL); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel)); + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t channel_on_execute(switch_core_session_t *session) +{ + + switch_channel_t *channel = NULL; + private_t *tech_pvt = NULL; + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + tech_pvt = switch_core_session_get_private(session); + assert(tech_pvt != NULL); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL EXECUTE\n", switch_channel_get_name(channel)); + + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t channel_on_hangup(switch_core_session_t *session) +{ + switch_channel_t *channel = NULL; + private_t *tech_pvt = NULL; + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + tech_pvt = switch_core_session_get_private(session); + assert(tech_pvt != NULL); + + switch_clear_flag_locked(tech_pvt, TFLAG_IO); + switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); + //switch_thread_cond_signal(tech_pvt->cond); + + if (tech_pvt->read_codec.implementation) { + switch_core_codec_destroy(&tech_pvt->read_codec); + } + + if (tech_pvt->write_codec.implementation) { + switch_core_codec_destroy(&tech_pvt->write_codec); + } + + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP\n", switch_channel_get_name(channel)); + switch_mutex_lock(globals.mutex); + globals.calls--; + if (globals.calls < 0) { + globals.calls = 0; + } + switch_mutex_unlock(globals.mutex); + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig) +{ + switch_channel_t *channel = NULL; + private_t *tech_pvt = NULL; + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + tech_pvt = switch_core_session_get_private(session); + assert(tech_pvt != NULL); + + switch (sig) { + case SWITCH_SIG_KILL: + switch_clear_flag_locked(tech_pvt, TFLAG_IO); + switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); + switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); + //switch_thread_cond_signal(tech_pvt->cond); + break; + case SWITCH_SIG_BREAK: + switch_set_flag_locked(tech_pvt, TFLAG_BREAK); + break; + default: + break; + } + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t channel_on_exchange_media(switch_core_session_t *session) +{ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL LOOPBACK\n"); + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t channel_on_soft_execute(switch_core_session_t *session) +{ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL TRANSMIT\n"); + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf) +{ + private_t *tech_pvt = switch_core_session_get_private(session); + switch_assert(tech_pvt != NULL); + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id) +{ + switch_channel_t *channel = NULL; + private_t *tech_pvt = NULL; + //switch_time_t started = switch_time_now(); + //unsigned int elapsed; + switch_byte_t *data; + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + tech_pvt = switch_core_session_get_private(session); + assert(tech_pvt != NULL); + tech_pvt->read_frame.flags = SFF_NONE; + *frame = NULL; + + while (switch_test_flag(tech_pvt, TFLAG_IO)) { + + if (switch_test_flag(tech_pvt, TFLAG_BREAK)) { + switch_clear_flag(tech_pvt, TFLAG_BREAK); + goto cng; + } + + if (!switch_test_flag(tech_pvt, TFLAG_IO)) { + return SWITCH_STATUS_FALSE; + } + + if (switch_test_flag(tech_pvt, TFLAG_IO) && switch_test_flag(tech_pvt, TFLAG_VOICE)) { + switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); + if (!tech_pvt->read_frame.datalen) { + continue; + } + *frame = &tech_pvt->read_frame; +#ifdef BIGENDIAN + if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) { + switch_swap_linear((*frame)->data, (int) (*frame)->datalen / 2); + } +#endif + return SWITCH_STATUS_SUCCESS; + } + + switch_yield(1000); + } + + + return SWITCH_STATUS_FALSE; + + cng: + data = (switch_byte_t *) tech_pvt->read_frame.data; + data[0] = 65; + data[1] = 0; + tech_pvt->read_frame.datalen = 2; + tech_pvt->read_frame.flags = SFF_CNG; + *frame = &tech_pvt->read_frame; + return SWITCH_STATUS_SUCCESS; + +} + +static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id) +{ + switch_channel_t *channel = NULL; + private_t *tech_pvt = NULL; + //switch_frame_t *pframe; + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + tech_pvt = switch_core_session_get_private(session); + assert(tech_pvt != NULL); + + if (!switch_test_flag(tech_pvt, TFLAG_IO)) { + return SWITCH_STATUS_FALSE; + } +#ifdef BIGENDIAN + if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) { + switch_swap_linear(frame->data, (int) frame->datalen / 2); + } +#endif + + + return SWITCH_STATUS_SUCCESS; + +} + +static switch_status_t channel_answer_channel(switch_core_session_t *session) +{ + private_t *tech_pvt; + switch_channel_t *channel = NULL; + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + tech_pvt = switch_core_session_get_private(session); + assert(tech_pvt != NULL); + + + return SWITCH_STATUS_SUCCESS; +} + + +static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg) +{ + switch_channel_t *channel; + private_t *tech_pvt; + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + tech_pvt = (private_t *) switch_core_session_get_private(session); + assert(tech_pvt != NULL); + + switch (msg->message_id) { + case SWITCH_MESSAGE_INDICATE_ANSWER: + { + channel_answer_channel(session); + } + break; + default: + break; + } + + return SWITCH_STATUS_SUCCESS; +} + +/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines + that allocate memory or you will have 1 channel with memory allocated from another channel's pool! +*/ +static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, + 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, pool)) != 0) { + private_t *tech_pvt; + switch_channel_t *channel; + switch_caller_profile_t *caller_profile; + + switch_core_session_add_stream(*new_session, NULL); + if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) { + channel = switch_core_session_get_channel(*new_session); + tech_init(tech_pvt, *new_session); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n"); + switch_core_session_destroy(new_session); + return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; + } + + if (outbound_profile) { + char name[128]; + + snprintf(name, sizeof(name), "SKYPIAX/%s", outbound_profile->destination_number); + switch_channel_set_name(channel, name); + + caller_profile = switch_caller_profile_clone(*new_session, outbound_profile); + switch_channel_set_caller_profile(channel, caller_profile); + tech_pvt->caller_profile = caller_profile; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Doh! no caller profile\n"); + switch_core_session_destroy(new_session); + return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; + } + + + + switch_channel_set_flag(channel, CF_OUTBOUND); + switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND); + switch_channel_set_state(channel, CS_INIT); + return SWITCH_CAUSE_SUCCESS; + } + + return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; + +} + +static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event) +{ + struct private_object *tech_pvt = switch_core_session_get_private(session); + char *body = switch_event_get_body(event); + switch_assert(tech_pvt != NULL); + + if (!body) { + body = ""; + } + + return SWITCH_STATUS_SUCCESS; +} + + + +switch_state_handler_table_t skypiax_state_handlers = { + /*.on_init */ channel_on_init, + /*.on_routing */ channel_on_routing, + /*.on_execute */ channel_on_execute, + /*.on_hangup */ channel_on_hangup, + /*.on_exchange_media */ channel_on_exchange_media, + /*.on_soft_execute */ channel_on_soft_execute +}; + +switch_io_routines_t skypiax_io_routines = { + /*.outgoing_channel */ channel_outgoing_channel, + /*.read_frame */ channel_read_frame, + /*.write_frame */ channel_write_frame, + /*.kill_channel */ channel_kill_channel, + /*.send_dtmf */ channel_send_dtmf, + /*.receive_message */ channel_receive_message, + /*.receive_event */ channel_receive_event +}; + +#ifndef NOTDEF +static switch_status_t load_config(void) +{ + char *cf = "skypiax.conf"; + switch_xml_t cfg, xml, settings, param, spans, myspan; + + memset(&globals, 0, sizeof(globals)); + switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, module_pool); + if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf); + return SWITCH_STATUS_TERM; + } + + if ((settings = switch_xml_child(cfg, "settings"))) { + for (param = switch_xml_child(settings, "param"); param; param = param->next) { + char *var = (char *) switch_xml_attr_soft(param, "name"); + char *val = (char *) switch_xml_attr_soft(param, "value"); + + if (!strcasecmp(var, "debug")) { + globals.debug = atoi(val); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "globals.debug=%d\n", globals.debug); + } else if (!strcasecmp(var, "hold-music")) { + switch_set_string(globals.hold_music, val); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "globals.hold_music=%s\n", globals.hold_music); + } else if (!strcmp(var, "port")) { + globals.port = atoi(val); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "globals.port=%d\n", globals.port); + } else if (!strcmp(var, "ip")) { + set_global_ip(val); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "globals.ip=%s\n", globals.ip); + } else if (!strcmp(var, "codec-master")) { + if (!strcasecmp(val, "us")) { + switch_set_flag(&globals, GFLAG_MY_CODEC_PREFS); + } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "globals.debug=%d\n", globals.debug); + } else if (!strcmp(var, "dialplan")) { + set_global_dialplan(val); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "globals.dialplan=%s\n", globals.dialplan); + } else if (!strcmp(var, "codec-prefs")) { + set_global_codec_string(val); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "globals.codec_string=%s\n", globals.codec_string); + globals.codec_order_last = switch_separate_string(globals.codec_string, ',', globals.codec_order, SWITCH_MAX_CODECS); + } else if (!strcmp(var, "codec-rates")) { + set_global_codec_rates_string(val); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "globals.codec_rates_string=%s\n", globals.codec_rates_string); + globals.codec_rates_last = switch_separate_string(globals.codec_rates_string, ',', globals.codec_rates, SWITCH_MAX_CODECS); + } + + } + } + + if ((spans = switch_xml_child(cfg, "analog_spans"))) { + for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) { + char *id = (char *) switch_xml_attr(myspan, "id"); + char *name = (char *) switch_xml_attr(myspan, "name"); + //FIXME zap_status_t zstatus = ZAP_FAIL; + char *context = "default"; + char *dialplan = "XML"; + char *tonegroup = NULL; + char *digit_timeout = NULL; + char *max_digits = NULL; + char *hotline = NULL; + char *dial_regex = NULL; + char *hold_music = NULL; + char *fail_dial_regex = NULL; + char *enable_callerid = "true"; + + uint32_t span_id = 0, to = 0, max = 0; + //FIXME zap_span_t *span = NULL; + //analog_option_t analog_options = ANALOG_OPTION_NONE; + + for (param = switch_xml_child(myspan, "param"); param; param = param->next) { + char *var = (char *) switch_xml_attr_soft(param, "name"); + char *val = (char *) switch_xml_attr_soft(param, "value"); + + if (!strcasecmp(var, "tonegroup")) { + tonegroup = val; + } else if (!strcasecmp(var, "digit_timeout") || !strcasecmp(var, "digit-timeout")) { + digit_timeout = val; + } else if (!strcasecmp(var, "context")) { + context = val; + } else if (!strcasecmp(var, "dialplan")) { + dialplan = val; + } else if (!strcasecmp(var, "dial-regex")) { + dial_regex = val; + } else if (!strcasecmp(var, "enable-callerid")) { + enable_callerid = val; + } else if (!strcasecmp(var, "fail-dial-regex")) { + fail_dial_regex = val; + } else if (!strcasecmp(var, "hold-music")) { + hold_music = val; + } else if (!strcasecmp(var, "max_digits") || !strcasecmp(var, "max-digits")) { + max_digits = val; + } else if (!strcasecmp(var, "hotline")) { + hotline = val; + } + + } + + if (!id && !name) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param 'id'\n"); + continue; + } + + + + if (!tonegroup) { + tonegroup = "us"; + } + + if (digit_timeout) { + to = atoi(digit_timeout); + } + + if (max_digits) { + max = atoi(max_digits); + } + + if (name) { + //FIXME zstatus = zap_span_find_by_name(name, &span); + } else { + if (switch_is_number(id)) { + span_id = atoi(id); + //FIXME zstatus = zap_span_find(span_id, &span); + } + + //FIXME if (zstatus != ZAP_SUCCESS) { + //FIXME zstatus = zap_span_find_by_name(id, &span); + //FIXME } + } + + //FIXME if (zstatus != ZAP_SUCCESS) { + //FIXME zap_log(ZAP_LOG_ERROR, "Error finding Skypiax span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name)); + //FIXME continue; + //FIXME } + + if (!span_id) { + //FIXME span_id = span->span_id; + } +//FIXME + /* + if (zap_configure_span("analog", span, on_analog_signal, + "tonemap", tonegroup, + "digit_timeout", &to, + "max_dialstr", &max, + "hotline", hotline, + "enable_callerid", enable_callerid, + TAG_END) != ZAP_SUCCESS) { + zap_log(ZAP_LOG_ERROR, "Error starting Skypiax span %d\n", span_id); + continue; + } + + SPAN_CONFIG[span->span_id].span = span; + switch_set_string(SPAN_CONFIG[span->span_id].context, context); + switch_set_string(SPAN_CONFIG[span->span_id].dialplan, dialplan); + //SPAN_CONFIG[span->span_id].analog_options = analog_options | globals.analog_options; + + if (dial_regex) { + switch_set_string(SPAN_CONFIG[span->span_id].dial_regex, dial_regex); + } + + if (fail_dial_regex) { + switch_set_string(SPAN_CONFIG[span->span_id].fail_dial_regex, fail_dial_regex); + } + + if (hold_music) { + switch_set_string(SPAN_CONFIG[span->span_id].hold_music, hold_music); + } + switch_copy_string(SPAN_CONFIG[span->span_id].type, "analog", sizeof(SPAN_CONFIG[span->span_id].type)); + zap_span_start(span); + */ + } + } + + + switch_xml_free(xml); + + return SWITCH_STATUS_SUCCESS; +} +#endif /* NOTDEF */ + + +#ifdef NOTDEF +static switch_status_t load_config(void) +{ + char *cf = "skypiax.conf"; + switch_xml_t cfg, xml, settings, param; + + memset(&globals, 0, sizeof(globals)); + switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, module_pool); + if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf); + return SWITCH_STATUS_TERM; + } + + if ((settings = switch_xml_child(cfg, "settings"))) { + for (param = switch_xml_child(settings, "param"); param; param = param->next) { + char *var = (char *) switch_xml_attr_soft(param, "name"); + char *val = (char *) switch_xml_attr_soft(param, "value"); + + if (!strcmp(var, "debug")) { + globals.debug = atoi(val); + } else if (!strcmp(var, "port")) { + globals.port = atoi(val); + } else if (!strcmp(var, "ip")) { + set_global_ip(val); + } else if (!strcmp(var, "codec-master")) { + if (!strcasecmp(val, "us")) { + switch_set_flag(&globals, GFLAG_MY_CODEC_PREFS); + } + } else if (!strcmp(var, "dialplan")) { + set_global_dialplan(val); + } else if (!strcmp(var, "codec-prefs")) { + set_global_codec_string(val); + globals.codec_order_last = switch_separate_string(globals.codec_string, ',', globals.codec_order, SWITCH_MAX_CODECS); + } else if (!strcmp(var, "codec-rates")) { + set_global_codec_rates_string(val); + globals.codec_rates_last = switch_separate_string(globals.codec_rates_string, ',', globals.codec_rates, SWITCH_MAX_CODECS); + } + } + } + + if (!globals.dialplan) { + set_global_dialplan("default"); + } + + if (!globals.port) { + globals.port = 4569; + } + + switch_xml_free(xml); + + return SWITCH_STATUS_SUCCESS; +} +#endif /* NOTDEF */ + +SWITCH_MODULE_LOAD_FUNCTION(mod_skypiax_load) +{ + + module_pool = pool; + + load_config(); + + *module_interface = switch_loadable_module_create_module_interface(pool, modname); + skypiax_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE); + skypiax_endpoint_interface->interface_name = "skypiax"; + skypiax_endpoint_interface->io_routines = &skypiax_io_routines; + skypiax_endpoint_interface->state_handler = &skypiax_state_handlers; + +/*****************************************/ +#ifdef CICOPET +{ + int i; + struct ast_config *cfg; + struct skypiax_pvt *tmp; + struct skypiax_pvt *p = NULL; + +#ifndef __CYGWIN__ + if (!XInitThreads()) + ast_log(LOG_ERROR, "Not initialized XInitThreads!\n"); +#endif /* __CYGWIN__ */ + + /* load skypiax.conf config file */ + cfg = ast_config_load(skypiax_config); + if (cfg != NULL) { + char *ctg = NULL; + int is_first_category = 1; + while ((ctg = ast_category_browse(cfg, ctg)) != NULL) { + /* create one interface for each category in skypiax.conf config file, first one set the defaults */ + tmp = skypiax_mkif(cfg, ctg, is_first_category); + if (tmp) { + DEBUGA_PBX + ("Created channel Skypiax: skypiax.conf category '[%s]', channel name '%s'" + "\n", SKYPIAX_P_LOG, ctg, tmp->name); + /* add interface to skypiax_iflist */ + tmp->next = skypiax_iflist; + skypiax_iflist = tmp; + /* next one will not be the first ;) */ + if (is_first_category == 1) { + is_first_category = 0; + skypiax_console_active = tmp->name; + } + } else { + ERRORA("Unable to create channel Skypiax from skypiax.conf category '[%s]'\n", + SKYPIAX_P_LOG, ctg); + /* if error, unload config from memory and return */ + ast_config_destroy(cfg); + ast_channel_unregister(&skypiax_tech); + if (option_debug > 10) { + DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG); + } + return -1; + } + /* do it for each category described in config */ + } + + /* we finished, unload config from memory */ + ast_config_destroy(cfg); + } else { + ERRORA("Unable to load skypiax_config skypiax.conf\n", SKYPIAX_P_LOG); + ast_channel_unregister(&skypiax_tech); + if (option_debug > 10) { + DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG); + } + return -1; + } +#ifndef ASTERISK_VERSION_1_6 + ast_cli_register_multiple(myclis, sizeof(myclis) / sizeof(struct ast_cli_entry)); +#endif /* ASTERISK_VERSION_1_6 */ + /* start to monitor the interfaces (skypiax_iflist) for the first time */ + if (skypiax_restart_monitor()) { + ERRORA("skypiax_restart_monitor failed, BAD\n", SKYPIAX_P_LOG); + if (option_debug > 10) { + DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG); + } + return -1; + } + if (option_debug > 10) { + DEBUGA_PBX("EXITING FUNC\n", SKYPIAX_P_LOG); + } + return 0; +} +#endif /* CICOPET */ + /********************************************/ + + /* indicate that the module should continue to be loaded */ + return SWITCH_STATUS_SUCCESS; +} + +/* +SWITCH_MODULE_RUNTIME_FUNCTION(mod_skypiax_runtime) +{ + return SWITCH_STATUS_TERM; +} +*/ + +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skypiax_shutdown) +{ + int x = 0; + + running = -1; + + while (running) { + if (x++ > 100) { + break; + } + switch_yield(20000); + } + return SWITCH_STATUS_SUCCESS; +} + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab: + */ + +#endif /* MOD_SKYPIAX */ +
participants (1)
-
Freeswitch SVN