static switch_status_t load_config(void) { char *cf = "reference.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; }
static switch_status_t switch_siren_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp) { if (codec_fmtp) { int bit_rate = 0; memset(codec_fmtp, '\0', sizeof(struct switch_codec_fmtp)); if (fmtp) { int x, argc; char *argv[10]; char *fmtp_dup = strdup(fmtp); switch_assert(fmtp_dup); argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0]))); for (x = 0; x < argc; x++) { char *data = argv[x]; char *arg; switch_assert(data); while (*data == ' ') { data++; } if ((arg = strchr(data, '='))) { *arg++ = '\0'; if (!strcasecmp(data, "bitrate")) { bit_rate = atoi(arg); } } } free(fmtp_dup); } codec_fmtp->bits_per_second = bit_rate; return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; }
static switch_status_t limit_state_handler(switch_core_session_t *session) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_channel_state_t state = switch_channel_get_state(channel); const char *vval = switch_channel_get_variable(channel, LIMIT_IGNORE_TRANSFER_VARIABLE); const char *backendlist = switch_channel_get_variable(channel, LIMIT_BACKEND_VARIABLE); if (zstr(backendlist)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unset limit backendlist!\n"); return SWITCH_STATUS_SUCCESS; } if (state >= CS_HANGUP || (state == CS_ROUTING && !switch_true(vval))) { int argc = 0; char *argv[6] = { 0 }; char *mydata = strdup(backendlist); int x; argc = switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof(argv[0]))); for (x = 0; x < argc; x++) { switch_limit_release(argv[x], session, NULL, NULL); } switch_core_event_hook_remove_state_change(session, limit_state_handler); /* Remove limit_backend variable so we register another hook if limit is called again */ switch_channel_set_variable(channel, LIMIT_BACKEND_VARIABLE, NULL); free(mydata); } return SWITCH_STATUS_SUCCESS; }
static switch_status_t switch_sangoma_init_ilbc(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings) { int mode = codec->implementation->microseconds_per_packet / 1000; if (codec->fmtp_in) { int x, argc; char *argv[10]; argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0]))); for (x = 0; x < argc; x++) { char *data = argv[x]; char *arg; switch_assert(data); while (*data == ' ') { data++; } if ((arg = strchr(data, '='))) { *arg++ = '\0'; if (!strcasecmp(data, "mode")) { mode = atoi(arg); } } } } codec->fmtp_out = switch_core_sprintf(codec->memory_pool, "mode=%d", mode); return switch_sangoma_init(codec, flags, codec_settings); }
static perl_parse_and_execute(PerlInterpreter * my_perl, char *input_code, char *setup_code) { int error = 0; if (*input_code == '~') { char *buff = input_code + 1; perl_parse(my_perl, xs_init, 3, embedding, NULL); if (setup_code) Perl_safe_eval(my_perl, setup_code); Perl_safe_eval(my_perl, buff); } else { int argc = 0; char *argv[128] = { 0 }; char *err; argv[0] = "FreeSWITCH"; argc++; argc += switch_separate_string(input_code, ' ', &argv[1], (sizeof(argv) / sizeof(argv[0])) - 1); if (!perl_parse(my_perl, xs_init, argc, argv, (char **) NULL)) { if (setup_code) { if (!Perl_safe_eval(my_perl, setup_code)) { perl_run(my_perl); } } } if ((err = SvPV(get_sv("@", TRUE), n_a)) && !zstr(err)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", err); } } }
SWITCH_DECLARE(uint32_t) switch_log_str2mask(const char *str) { int argc = 0, x = 0; char *argv[10] = { 0 }; uint32_t mask = 0; char *p = strdup(str); switch_log_level_t level; switch_assert(p); if ((argc = switch_separate_string(p, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) { for (x = 0; x < argc && argv[x]; x++) { if (!strcasecmp(argv[x], "all")) { mask = 0xFF; break; } else { level = switch_log_str2level(argv[x]); if (level != SWITCH_LOG_INVALID) { mask |= (1 << level); } } } } free(p); return mask; }
void conference_loop_exec_app(conference_member_t *member, caller_control_action_t *action) { char *app = NULL; char *arg = ""; char *argv[2] = { 0 }; int argc; char *mydata = NULL; switch_event_t *event = NULL; switch_channel_t *channel = NULL; if (!action->expanded_data) return; if (test_eflag(member->conference, EFLAG_DTMF) && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { conference_member_add_event_data(member, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "execute_app"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application", action->expanded_data); switch_event_fire(&event); } mydata = strdup(action->expanded_data); switch_assert(mydata); if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { if (argc > 0) { app = argv[0]; } if (argc > 1) { arg = argv[1]; } } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_ERROR, "Empty execute app string [%s]\n", (char *) action->expanded_data); goto done; } if (!app) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_ERROR, "Unable to find application.\n"); goto done; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_INFO, "Execute app: %s, %s\n", app, arg); channel = switch_core_session_get_channel(member->session); switch_channel_set_app_flag(channel, CF_APP_TAGGED); switch_core_session_set_read_codec(member->session, NULL); switch_core_session_execute_application(member->session, app, arg); switch_core_session_set_read_codec(member->session, &member->read_codec); switch_channel_clear_app_flag(channel, CF_APP_TAGGED); done: switch_safe_free(mydata); return; }
static switch_status_t skinny_api_cmd_profile_device_send_data(const char *profile_name, const char *device_name, const char *message_type, char *params, const char *body, switch_stream_handle_t *stream) { skinny_profile_t *profile; if ((profile = skinny_find_profile(profile_name))) { listener_t *listener = NULL; skinny_profile_find_listener_by_device_name(profile, device_name, &listener); if(listener) { switch_event_t *event = NULL; char *argv[64] = { 0 }; int argc = 0; int x = 0; /* skinny::user_to_device event */ skinny_device_event(listener, &event, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_USER_TO_DEVICE); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Message-Id-String", "%s", message_type); argc = switch_separate_string(params, ';', argv, (sizeof(argv) / sizeof(argv[0]))); for (x = 0; x < argc; x++) { char *var_name, *var_value = NULL; var_name = argv[x]; if (var_name && (var_value = strchr(var_name, '='))) { *var_value++ = '\0'; } if (zstr(var_name)) { stream->write_function(stream, "-ERR No variable specified\n"); } else { char *tmp = switch_mprintf("Skinny-UserToDevice-%s", var_name); switch_event_add_header(event, SWITCH_STACK_BOTTOM, tmp, "%s", var_value); switch_safe_free(tmp); /* switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Application-Id", "%d", request->data.extended_data.application_id); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Line-Instance", "%d", request->data.extended_data.line_instance); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Call-Id", "%d", request->data.extended_data.call_id); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Transaction-Id", "%d", request->data.extended_data.transaction_id); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Data-Length", "%d", request->data.extended_data.data_length); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Sequence-Flag", "%d", request->data.extended_data.sequence_flag); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Display-Priority", "%d", request->data.extended_data.display_priority); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Conference-Id", "%d", request->data.extended_data.conference_id); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-App-Instance-Id", "%d", request->data.extended_data.app_instance_id); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Routing-Id", "%d", request->data.extended_data.routing_id); */ } } switch_event_add_body(event, "%s", body); switch_event_fire(&event); stream->write_function(stream, "+OK\n"); } else { stream->write_function(stream, "Listener not found!\n"); } } else { stream->write_function(stream, "Profile not found!\n"); } return SWITCH_STATUS_SUCCESS; }
static void ladspa_parse(switch_core_session_t *session, const char *data) { char *argv[5] = { 0 }; int argc; char *lbuf; if (data) { lbuf = strdup(data); argc = switch_separate_string(lbuf, '|', argv, (sizeof(argv) / sizeof(argv[0]))); ladspa_session(session, argv[0], argv[1], argv[2], argv[3]); free(lbuf); } }
static switch_status_t switch_speex_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp) { if (codec_fmtp) { speex_codec_settings_t *codec_settings = NULL; if (codec_fmtp->private_info) { codec_settings = codec_fmtp->private_info; memcpy(codec_settings, &default_codec_settings, sizeof(*codec_settings)); } if (fmtp) { int x, argc; char *argv[10]; char *fmtp_dup = strdup(fmtp); switch_assert(fmtp_dup); argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0]))); for (x = 0; x < argc; x++) { char *data = argv[x]; char *arg; switch_assert(data); while (*data == ' ') { data++; } if ((arg = strchr(data, '='))) { *arg++ = '\0'; /* if (!strcasecmp(data, "bitrate")) { bit_rate = atoi(arg); } */ /* if (codec_settings) { if (!strcasecmp(data, "vad")) { bit_rate = atoi(arg); } } */ } } free(fmtp_dup); } /*codec_fmtp->bits_per_second = bit_rate;*/ return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; }
void conference_loop_transfer(conference_member_t *member, caller_control_action_t *action) { char *exten = NULL; char *dialplan = "XML"; char *context = "default"; char *argv[3] = { 0 }; int argc; char *mydata = NULL; switch_event_t *event; if (test_eflag(member->conference, EFLAG_DTMF) && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { conference_member_add_event_data(member, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "transfer"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Dialplan", action->expanded_data); switch_event_fire(&event); } conference_utils_member_clear_flag_locked(member, MFLAG_RUNNING); if ((mydata = switch_core_session_strdup(member->session, action->expanded_data))) { if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { if (argc > 0) { exten = argv[0]; } if (argc > 1) { dialplan = argv[1]; } if (argc > 2) { context = argv[2]; } } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_ERROR, "Empty transfer string [%s]\n", (char *) action->expanded_data); goto done; } } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_ERROR, "Unable to allocate memory to duplicate transfer data.\n"); goto done; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_INFO, "Transfering to: %s, %s, %s\n", exten, dialplan, context); switch_ivr_session_transfer(member->session, exten, dialplan, context); done: return; }
static switch_status_t exec_app(switch_core_session_t *session, const char *app_string) { switch_status_t status; char *strings[2] = { 0 }; char *dup; if (!app_string) { return SWITCH_STATUS_FALSE; } dup = strdup(app_string); switch_assert(dup); switch_separate_string(dup, ' ', strings, sizeof(strings) / sizeof(strings[0])); status = switch_core_session_execute_application(session, strings[0], strings[1]); free(dup); return status; }
static switch_status_t cdr_mongo_authenticate() { switch_status_t status = SWITCH_STATUS_SUCCESS; mongo_error_t db_status; char *ns_tmp, *ns_split[2]; /* Split namespace db.collection into separate vars */ switch_strdup(ns_tmp, globals.mongo_namespace); switch_separate_string(ns_tmp, '.', ns_split, 2); db_status = mongo_cmd_authenticate(globals.mongo_conn, ns_split[0], globals.mongo_username, globals.mongo_password); if (db_status != MONGO_OK) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_cmd_authenticate: authentication failed\n"); status = SWITCH_STATUS_FALSE; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Successfully authenticated %s@%s\n", globals.mongo_username, ns_split[0]); } switch_safe_free(ns_tmp); return status; }
/** * Add a definition for a tag * @param tag the name * @param attribs_fn the function to handle the tag attributes * @param cdata_fn the function to handler the tag CDATA * @param children_tags comma-separated list of valid child tag names * @return the definition */ static struct tag_def *add_tag_def(const char *tag, tag_attribs_fn attribs_fn, tag_cdata_fn cdata_fn, const char *children_tags) { struct tag_def *def = switch_core_alloc(globals.pool, sizeof(*def)); switch_core_hash_init(&def->children_tags, globals.pool); if (!zstr(children_tags)) { char *children_tags_dup = switch_core_strdup(globals.pool, children_tags); char *tags[32] = { 0 }; int tag_count = switch_separate_string(children_tags_dup, ',', tags, sizeof(tags) / sizeof(tags[0])); if (tag_count) { int i; for (i = 0; i < tag_count; i++) { switch_core_hash_insert(def->children_tags, tags[i], tags[i]); } } } def->attribs_fn = attribs_fn; def->cdata_fn = cdata_fn; def->is_root = SWITCH_FALSE; switch_core_hash_insert(globals.tag_defs, tag, def); return def; }
static switch_status_t skinny_api_list_devices(const char *line, const char *cursor, switch_console_callback_match_t **matches) { struct match_helper h = { 0 }; switch_status_t status = SWITCH_STATUS_FALSE; skinny_profile_t *profile = NULL; char *sql; char *myline; char *argv[1024] = { 0 }; int argc = 0; if (!(myline = strdup(line))) { status = SWITCH_STATUS_MEMERR; return status; } if (!(argc = switch_separate_string(myline, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) || argc < 4) { return status; } if(!strcasecmp(argv[1], "profile")) {/* skinny profile <profile_name> ... */ profile = skinny_find_profile(argv[2]); } else if(!strcasecmp(argv[2], "profile")) {/* skinny status profile <profile_name> ... */ profile = skinny_find_profile(argv[3]); } if(profile) { if ((sql = switch_mprintf("SELECT name FROM skinny_devices"))) { skinny_execute_sql_callback(profile, profile->sql_mutex, sql, skinny_api_list_devices_callback, &h); switch_safe_free(sql); } } if (h.my_matches) { *matches = h.my_matches; status = SWITCH_STATUS_SUCCESS; } return status; }
static void transfer_call(switch_core_session_t *session, char *destination) { char *argv[4] = { 0 }; const char *uuid; switch_channel_t *channel = switch_core_session_get_channel(session); char *mydup; if (!destination) { return; } mydup = strdup(destination); switch_assert(mydup); switch_separate_string(mydup, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); /* Find the uuid of our B leg. If it exists, transfer it first */ if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) { switch_core_session_t *b_session; /* Get info on the B leg */ if ((b_session = switch_core_session_locate(uuid))) { /* Make sure we are in the media path on B leg */ switch_ivr_media(uuid, SMF_REBRIDGE); /* Transfer the B leg */ switch_ivr_session_transfer(b_session, argv[0], argv[1], argv[2]); switch_core_session_rwunlock(b_session); } } /* Make sure we are in the media path on A leg */ uuid = switch_core_session_get_uuid(session); switch_ivr_media(uuid, SMF_REBRIDGE); /* Transfer the A leg */ switch_ivr_session_transfer(session, argv[0], argv[1], argv[2]); free(mydup); }
/** * Do TTS as file format * @param handle * @param path the inline SSML * @return SWITCH_STATUS_SUCCESS if opened */ static switch_status_t tts_file_open(switch_file_handle_t *handle, const char *path) { switch_status_t status = SWITCH_STATUS_SUCCESS; struct tts_context *context = switch_core_alloc(handle->memory_pool, sizeof(*context)); char *arg_string = switch_core_strdup(handle->memory_pool, path); char *args[3] = { 0 }; int argc = switch_separate_string(arg_string, '|', args, (sizeof(args) / sizeof(args[0]))); char *module; char *voice; char *document; /* path is module:(optional)profile|voice|{param1=val1,param2=val2}TTS document */ if (argc != 3) { return SWITCH_STATUS_FALSE; } module = args[0]; voice = args[1]; document = args[2]; memset(context, 0, sizeof(*context)); context->flags = SWITCH_SPEECH_FLAG_NONE; if ((status = switch_core_speech_open(&context->sh, module, voice, handle->samplerate, handle->interval, &context->flags, NULL)) == SWITCH_STATUS_SUCCESS) { if ((status = switch_core_speech_feed_tts(&context->sh, document, &context->flags)) == SWITCH_STATUS_SUCCESS) { handle->channels = 1; handle->samples = 0; handle->format = 0; handle->sections = 0; handle->seekable = 0; handle->speed = 0; context->max_frame_size = handle->samplerate / 1000 * SWITCH_MAX_INTERVAL; } else { switch_core_speech_close(&context->sh, &context->flags); } } handle->private_info = context; return status; }
static char *print_json(switch_memory_pool_t *pool, http_data_t *http_data) { struct json_object *top = NULL; struct json_object *headers = NULL; char *data = NULL; switch_curl_slist_t *header = http_data->headers; top = json_object_new_object(); headers = json_object_new_array(); json_object_object_add(top, "status_code", json_object_new_int(http_data->http_response_code)); if (http_data->http_response) { json_object_object_add(top, "body", json_object_new_string(http_data->http_response)); } /* parse header data */ while (header) { struct json_object *obj = NULL; /* remove trailing \r */ if ((data = strrchr(header->data, '\r'))) { *data = '\0'; } if (zstr(header->data)) { header = header->next; continue; } if ((data = strchr(header->data, ':'))) { *data = '\0'; data++; while (*data == ' ' && *data != '\0') { data++; } obj = json_object_new_object(); json_object_object_add(obj, "key", json_object_new_string(header->data)); json_object_object_add(obj, "value", json_object_new_string(data)); json_object_array_add(headers, obj); } else { if (!strncmp("HTTP", header->data, 4)) { char *argv[3] = { 0 }; int argc; if ((argc = switch_separate_string(header->data, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { if (argc > 2) { json_object_object_add(top, "version", json_object_new_string(argv[0])); json_object_object_add(top, "phrase", json_object_new_string(argv[2])); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unparsable header: argc: %d\n", argc); } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Starts with HTTP but not parsable: %s\n", header->data); } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unparsable header: %s\n", header->data); } } header = header->next; } json_object_object_add(top, "headers", headers); data = switch_core_strdup(pool, json_object_to_json_string(top)); json_object_put(top); /* should free up all children */ return data; }
static switch_status_t switch_silk_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp) { if (codec_fmtp) { silk_codec_settings_t *codec_settings = NULL; if (codec_fmtp->private_info) { codec_settings = codec_fmtp->private_info; memcpy(codec_settings, &default_codec_settings, sizeof(*codec_settings)); } if (fmtp) { int x, argc; char *argv[10]; char *fmtp_dup = strdup(fmtp); switch_assert(fmtp_dup); argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0]))); for (x = 0; x < argc; x++) { char *data = argv[x]; char *arg; switch_assert(data); while (*data == ' ') { data++; } if ((arg = strchr(data, '='))) { *arg++ = '\0'; if (codec_settings) { if (!strcasecmp(data, "useinbandfec")) { if (switch_true(arg)) { codec_settings->useinbandfec = 1; } } if (!strcasecmp(data, "usedtx")) { if (switch_true(arg)) { codec_settings->usedtx = 1; } } if (!strcasecmp(data, "maxaveragebitrate")) { codec_settings->maxaveragebitrate = atoi(arg); switch(codec_fmtp->actual_samples_per_second) { case 8000: { if(codec_settings->maxaveragebitrate < 6000 || codec_settings->maxaveragebitrate > 20000) { codec_settings->maxaveragebitrate = 20000; } break; } case 12000: { if(codec_settings->maxaveragebitrate < 7000 || codec_settings->maxaveragebitrate > 25000) { codec_settings->maxaveragebitrate = 25000; } break; } case 16000: { if(codec_settings->maxaveragebitrate < 8000 || codec_settings->maxaveragebitrate > 30000) { codec_settings->maxaveragebitrate = 30000; } break; } case 24000: { if(codec_settings->maxaveragebitrate < 12000 || codec_settings->maxaveragebitrate > 40000) { codec_settings->maxaveragebitrate = 40000; } break; } default: /* this should never happen but 20000 is common among all rates */ codec_settings->maxaveragebitrate = 20000; break; } } } } } free(fmtp_dup); } //codec_fmtp->bits_per_second = bit_rate; return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; }
static switch_status_t switch_amr_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp) { if (codec_fmtp) { amr_codec_settings_t *codec_settings = NULL; if (codec_fmtp->private_info) { codec_settings = codec_fmtp->private_info; memcpy(codec_settings, &default_codec_settings, sizeof(*codec_settings)); } if (fmtp) { int x, argc; char *argv[10]; char *fmtp_dup = strdup(fmtp); switch_assert(fmtp_dup); argc = switch_separate_string((char *) fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0]))); for (x = 0; x < argc; x++) { char *data = argv[x]; char *arg; switch_assert(data); while (*data == ' ') { data++; } if ((arg = strchr(data, '='))) { *arg++ = '\0'; /* if (!strcasecmp(data, "bitrate")) { bit_rate = atoi(arg); } */ if (codec_settings) { if (!strcasecmp(data, "octet-align")) { if (atoi(arg)) { switch_set_flag(codec_settings, AMR_OPT_OCTET_ALIGN); } } else if (!strcasecmp(data, "mode-change-neighbor")) { if (atoi(arg)) { switch_set_flag(codec_settings, AMR_OPT_MODE_CHANGE_NEIGHBOR); } } else if (!strcasecmp(data, "crc")) { if (atoi(arg)) { switch_set_flag(codec_settings, AMR_OPT_CRC); } } else if (!strcasecmp(data, "robust-sorting")) { if (atoi(arg)) { switch_set_flag(codec_settings, AMR_OPT_ROBUST_SORTING); } } else if (!strcasecmp(data, "interveaving")) { if (atoi(arg)) { switch_set_flag(codec_settings, AMR_OPT_INTERLEAVING); } } else if (!strcasecmp(data, "mode-change-period")) { codec_settings->change_period = atoi(arg); } else if (!strcasecmp(data, "ptime")) { codec_settings->ptime = (switch_byte_t) atoi(arg); } else if (!strcasecmp(data, "channels")) { codec_settings->channels = (switch_byte_t) atoi(arg); } else if (!strcasecmp(data, "maxptime")) { codec_settings->max_ptime = (switch_byte_t) atoi(arg); } else if (!strcasecmp(data, "mode-set")) { int y, m_argc; char *m_argv[7]; m_argc = switch_separate_string(arg, ',', m_argv, (sizeof(m_argv) / sizeof(m_argv[0]))); for (y = 0; y < m_argc; y++) { codec_settings->enc_modes |= (1 << atoi(m_argv[y])); } } else if (!strcasecmp(data, "dtx")) { codec_settings->dtx_mode = (atoi(arg)) ? AMR_DTX_ENABLED : AMR_DTX_DISABLED; } } } } free(fmtp_dup); } //codec_fmtp->bits_per_second = bit_rate; return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; }
SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf_string(switch_core_session_t *session, const char *dtmf_string) { char *p; switch_dtmf_t dtmf = { 0, switch_core_default_dtmf_duration(0) }; int sent = 0, dur; char *string; int i, argc; char *argv[256]; int dur_total = 0; switch_assert(session != NULL); if (switch_channel_down(session->channel)) { return SWITCH_STATUS_FALSE; } if (zstr(dtmf_string)) { return SWITCH_STATUS_FALSE; } if (strlen(dtmf_string) > 99) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Attempt to send very large dtmf string ignored!\n"); return SWITCH_STATUS_FALSE; } string = switch_core_session_strdup(session, dtmf_string); argc = switch_separate_string(string, '+', argv, (sizeof(argv) / sizeof(argv[0]))); if (argc) { switch_channel_pre_answer(session->channel); } for (i = 0; i < argc; i++) { dtmf.duration = switch_core_default_dtmf_duration(0); dur = switch_core_default_dtmf_duration(0) / 8; if ((p = strchr(argv[i], '@'))) { *p++ = '\0'; if ((dur = atoi(p)) > 50) { dtmf.duration = dur * 8; } } if (dtmf.duration > switch_core_max_dtmf_duration(0)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s EXCESSIVE DTMF DIGIT [%c] LEN [%d]\n", switch_channel_get_name(session->channel), dtmf.digit, dtmf.duration); dtmf.duration = switch_core_max_dtmf_duration(0); } else if (dtmf.duration < switch_core_min_dtmf_duration(0)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s SHORT DTMF DIGIT [%c] LEN [%d]\n", switch_channel_get_name(session->channel), dtmf.digit, dtmf.duration); dtmf.duration = switch_core_min_dtmf_duration(0); } else if (!dtmf.duration) { dtmf.duration = switch_core_default_dtmf_duration(0); } for (p = argv[i]; p && *p; p++) { if (is_dtmf(*p)) { dtmf.digit = *p; if (switch_core_session_send_dtmf(session, &dtmf) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s send dtmf\ndigit=%c ms=%u samples=%u\n", switch_channel_get_name(session->channel), dtmf.digit, dur, dtmf.duration); sent++; dur_total += dtmf.duration + 2000; /* account for 250ms pause */ } } } if (dur_total) { char tmp[32] = ""; switch_snprintf(tmp, sizeof(tmp), "%d", dur_total / 8); switch_channel_set_variable(session->channel, "last_dtmf_duration", tmp); } } return sent ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; }
static switch_status_t switch_opus_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp) { if (codec_fmtp) { opus_codec_settings_t local_settings = { 0 }; opus_codec_settings_t *codec_settings = &local_settings; if (codec_fmtp->private_info) { codec_settings = codec_fmtp->private_info; if (zstr(fmtp)) { memcpy(codec_settings, &default_codec_settings, sizeof(*codec_settings)); } } if (fmtp) { int x, argc; char *argv[10]; char *fmtp_dup = strdup(fmtp); switch_assert(fmtp_dup); argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0]))); for (x = 0; x < argc; x++) { char *data = argv[x]; char *arg; switch_assert(data); while (*data == ' ') { data++; } if ((arg = strchr(data, '='))) { *arg++ = '\0'; if (codec_settings) { if (!strcasecmp(data, "useinbandfec")) { codec_settings->useinbandfec = switch_true(arg); } if (!strcasecmp(data, "usedtx")) { codec_settings->usedtx = switch_true(arg); } if (!strcasecmp(data, "sprop-maxcapturerate")) { codec_settings->sprop_maxcapturerate = atoi(arg); } if (!strcasecmp(data, "maxptime")) { codec_settings->maxptime = atoi(arg); } if (!strcasecmp(data, "minptime")) { codec_settings->minptime = atoi(arg); } if (!strcasecmp(data, "ptime")) { codec_settings->ptime = atoi(arg); codec_fmtp->microseconds_per_packet = codec_settings->ptime * 1000; } if (!strcasecmp(data, "samplerate")) { codec_settings->samplerate = atoi(arg); codec_fmtp->actual_samples_per_second = codec_settings->samplerate; } if (!strcasecmp(data, "stereo")) { codec_settings->stereo = atoi(arg); codec_fmtp->stereo = codec_settings->stereo; } if (!strcasecmp(data, "maxaveragebitrate")) { codec_settings->maxaveragebitrate = atoi(arg); if ( codec_settings->maxaveragebitrate < 6000 || codec_settings->maxaveragebitrate > 510000 ) { codec_settings->maxaveragebitrate = 0; /* values outside the range between 6000 and 510000 SHOULD be ignored */ } } if (!strcasecmp(data, "maxplaybackrate")) { codec_settings->maxplaybackrate = atoi(arg); if ( codec_settings->maxplaybackrate != 8000 && codec_settings->maxplaybackrate != 12000 && codec_settings->maxplaybackrate != 16000 && codec_settings->maxplaybackrate != 24000 && codec_settings->maxplaybackrate != 48000) { codec_settings->maxplaybackrate = 0; /* value not supported */ } } } } } free(fmtp_dup); } return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; }
static void switch_core_standard_on_routing(switch_core_session_t *session) { switch_dialplan_interface_t *dialplan_interface = NULL; switch_caller_profile_t *caller_profile; switch_caller_extension_t *extension = NULL; char *expanded = NULL; char *dpstr = NULL; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard ROUTING\n", switch_channel_get_name(session->channel)); switch_channel_set_variable(session->channel, "call_uuid", switch_core_session_get_uuid(session)); if ((switch_channel_test_flag(session->channel, CF_ANSWERED) || switch_channel_test_flag(session->channel, CF_EARLY_MEDIA) || switch_channel_test_flag(session->channel, CF_SIGNAL_BRIDGE_TTL)) && switch_channel_test_flag(session->channel, CF_PROXY_MODE)) { switch_ivr_media(session->uuid_str, SMF_NONE); } if ((caller_profile = switch_channel_get_caller_profile(session->channel)) == 0) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't get profile!\n"); switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); return; } else { char *dp[25]; int argc, x, count = 0; if ((extension = switch_channel_get_queued_extension(session->channel))) { switch_channel_set_caller_extension(session->channel, extension); switch_channel_set_state(session->channel, CS_EXECUTE); goto end; } if (!zstr(caller_profile->dialplan)) { if ((dpstr = switch_core_session_strdup(session, caller_profile->dialplan))) { expanded = switch_channel_expand_variables(session->channel, dpstr); argc = switch_separate_string(expanded, ',', dp, (sizeof(dp) / sizeof(dp[0]))); for (x = 0; x < argc; x++) { char *dpname = dp[x]; char *dparg = NULL; if (dpname) { if ((dparg = strchr(dpname, ':'))) { *dparg++ = '\0'; } } else { continue; } if (!(dialplan_interface = switch_loadable_module_get_dialplan_interface(dpname))) { continue; } count++; extension = dialplan_interface->hunt_function(session, dparg, NULL); UNPROTECT_INTERFACE(dialplan_interface); if (extension) { switch_channel_set_caller_extension(session->channel, extension); switch_channel_set_state(session->channel, CS_EXECUTE); goto end; } } } } if (!count) { if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { if (switch_channel_test_flag(session->channel, CF_ANSWERED)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No Dialplan on answered channel, changing state to HANGUP\n"); switch_channel_hangup(session->channel, SWITCH_CAUSE_NO_ROUTE_DESTINATION); } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No Dialplan, changing state to CONSUME_MEDIA\n"); switch_channel_set_state(session->channel, CS_CONSUME_MEDIA); } goto end; } } } if (!extension) { if (switch_ivr_blind_transfer_ack(session, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "No Route, Aborting\n"); switch_channel_hangup(session->channel, SWITCH_CAUSE_NO_ROUTE_DESTINATION); } } end: if (expanded && dpstr && expanded != dpstr) { free(expanded); } }
/* the main application entry point */ int main(int argc, char *argv[]) { char pid_path[PATH_MAX] = ""; /* full path to the pid file */ char pid_buffer[32] = ""; /* pid string */ char old_pid_buffer[32] = ""; /* pid string */ switch_size_t pid_len, old_pid_len; const char *err = NULL; /* error value for return from freeswitch initialization */ #ifndef WIN32 switch_bool_t nf = SWITCH_FALSE; /* TRUE if we are running in nofork mode */ switch_bool_t do_wait = SWITCH_FALSE; char *runas_user = NULL; char *runas_group = NULL; int fds[2] = { 0, 0 }; #else switch_bool_t win32_service = SWITCH_FALSE; #endif switch_bool_t nc = SWITCH_FALSE; /* TRUE if we are running in noconsole mode */ pid_t pid = 0; int i, x; char *opts; char opts_str[1024] = ""; char *local_argv[1024] = { 0 }; int local_argc = argc; char *arg_argv[128] = { 0 }; int alt_dirs = 0, log_set = 0, run_set = 0, do_kill = 0; int priority = 0; #ifdef __sun switch_core_flag_t flags = SCF_USE_SQL; #else switch_core_flag_t flags = SCF_USE_SQL | SCF_USE_AUTO_NAT | SCF_USE_NAT_MAPPING | SCF_CALIBRATE_CLOCK | SCF_USE_CLOCK_RT; #endif int ret = 0; switch_status_t destroy_status; switch_file_t *fd; switch_memory_pool_t *pool = NULL; #ifdef HAVE_SETRLIMIT #ifndef FS_64BIT switch_bool_t waste = SWITCH_FALSE; #endif #endif for (x = 0; x < argc; x++) { local_argv[x] = argv[x]; } if ((opts = getenv("FREESWITCH_OPTS"))) { strncpy(opts_str, opts, sizeof(opts_str) - 1); i = switch_separate_string(opts_str, ' ', arg_argv, (sizeof(arg_argv) / sizeof(arg_argv[0]))); for (x = 0; x < i; x++) { local_argv[local_argc++] = arg_argv[x]; } } if (local_argv[0] && strstr(local_argv[0], "freeswitchd")) { nc = SWITCH_TRUE; } for (x = 1; x < local_argc; x++) { if (switch_strlen_zero(local_argv[x])) continue; if (!strcmp(local_argv[x], "-help") || !strcmp(local_argv[x], "-h") || !strcmp(local_argv[x], "-?")) { printf("%s\n", usage); exit(EXIT_SUCCESS); } #ifdef WIN32 if (x == 1 && !strcmp(local_argv[x], "-service")) { /* New installs will always have the service name specified, but keep a default for compat */ x++; if (!switch_strlen_zero(local_argv[x])) { switch_copy_string(service_name, local_argv[x], SERVICENAME_MAXLEN); } else { switch_copy_string(service_name, SERVICENAME_DEFAULT, SERVICENAME_MAXLEN); } win32_service = SWITCH_TRUE; continue; } else if (x == 1 && !strcmp(local_argv[x], "-install")) { char servicePath[PATH_MAX]; char exePath[PATH_MAX]; SC_HANDLE hService; SC_HANDLE hSCManager; SERVICE_DESCRIPTION desc; desc.lpDescription = "The FreeSWITCH service."; x++; if (!switch_strlen_zero(local_argv[x])) { switch_copy_string(service_name, local_argv[x], SERVICENAME_MAXLEN); } else { switch_copy_string(service_name, SERVICENAME_DEFAULT, SERVICENAME_MAXLEN); } GetModuleFileName(NULL, exePath, sizeof(exePath)); snprintf(servicePath, sizeof(servicePath), "%s -service %s", exePath, service_name); /* Perform service installation */ hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (!hSCManager) { fprintf(stderr, "Could not open service manager (%u).\n", GetLastError()); exit(EXIT_FAILURE); } hService = CreateService(hSCManager, service_name, service_name, GENERIC_READ | GENERIC_EXECUTE | SERVICE_CHANGE_CONFIG, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, servicePath, NULL, NULL, NULL, NULL, /* Service start name */ NULL); if (!hService) { fprintf(stderr, "Error creating freeswitch service (%u).\n", GetLastError()); CloseServiceHandle(hSCManager); exit(EXIT_FAILURE); } /* Set desc, and don't care if it succeeds */ if (!ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &desc)) { fprintf(stderr, "FreeSWITCH installed, but could not set the service description (%u).\n", GetLastError()); } CloseServiceHandle(hService); CloseServiceHandle(hSCManager); exit(EXIT_SUCCESS); } else if (x == 1 && !strcmp(local_argv[x], "-uninstall")) { SC_HANDLE hService; SC_HANDLE hSCManager; BOOL deleted; x++; if (!switch_strlen_zero(local_argv[x])) { switch_copy_string(service_name, local_argv[x], SERVICENAME_MAXLEN); } else { switch_copy_string(service_name, SERVICENAME_DEFAULT, SERVICENAME_MAXLEN); } /* Do the uninstallation */ hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (!hSCManager) { fprintf(stderr, "Could not open service manager (%u).\n", GetLastError()); exit(EXIT_FAILURE); } hService = OpenService(hSCManager, service_name, DELETE); if (!hService) { fprintf(stderr, "Error opening service (%u).\n", GetLastError()); CloseServiceHandle(hSCManager); exit(EXIT_FAILURE); } /* remove the service! */ deleted = DeleteService(hService); if (!deleted) { fprintf(stderr, "Error deleting service (%u).\n", GetLastError()); } CloseServiceHandle(hService); CloseServiceHandle(hSCManager); exit(deleted ? EXIT_SUCCESS : EXIT_FAILURE); } else if (!strcmp(local_argv[x], "-monotonic-clock")) { flags |= SCF_USE_WIN32_MONOTONIC; } #else else if (!strcmp(local_argv[x], "-u")) { x++; if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "Option '%s' requires an argument!\n", local_argv[x - 1]); exit(EXIT_FAILURE); } runas_user = local_argv[x]; } else if (!strcmp(local_argv[x], "-g")) { x++; if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "Option '%s' requires an argument!\n", local_argv[x - 1]); exit(EXIT_FAILURE); } runas_group = local_argv[x]; } else if (!strcmp(local_argv[x], "-nf")) { nf = SWITCH_TRUE; } else if (!strcmp(local_argv[x], "-version")) { fprintf(stdout, "FreeSWITCH version: %s (%s)\n", SWITCH_VERSION_FULL, SWITCH_VERSION_REVISION_HUMAN); exit(EXIT_SUCCESS); } #endif #ifdef HAVE_SETRLIMIT else if (!strcmp(local_argv[x], "-core")) { struct rlimit rlp; memset(&rlp, 0, sizeof(rlp)); rlp.rlim_cur = RLIM_INFINITY; rlp.rlim_max = RLIM_INFINITY; setrlimit(RLIMIT_CORE, &rlp); } else if (!strcmp(local_argv[x], "-waste")) { #ifndef FS_64BIT fprintf(stderr, "WARNING: Wasting up to 8 megs of memory per thread.\n"); sleep(2); waste = SWITCH_TRUE; #endif } else if (!strcmp(local_argv[x], "-no-auto-stack")) { #ifndef FS_64BIT waste = SWITCH_TRUE; #endif } #endif else if (!strcmp(local_argv[x], "-hp") || !strcmp(local_argv[x], "-rp")) { priority = 2; } else if (!strcmp(local_argv[x], "-lp")) { priority = -1; } else if (!strcmp(local_argv[x], "-np")) { priority = 1; } else if (!strcmp(local_argv[x], "-nosql")) { flags &= ~SCF_USE_SQL; } else if (!strcmp(local_argv[x], "-nonat")) { flags &= ~SCF_USE_AUTO_NAT; } else if (!strcmp(local_argv[x], "-nonatmap")) { flags &= ~SCF_USE_NAT_MAPPING; } else if (!strcmp(local_argv[x], "-heavy-timer")) { flags |= SCF_USE_HEAVY_TIMING; } else if (!strcmp(local_argv[x], "-nort")) { flags &= ~SCF_USE_CLOCK_RT; } else if (!strcmp(local_argv[x], "-nocal")) { flags &= ~SCF_CALIBRATE_CLOCK; } else if (!strcmp(local_argv[x], "-vg")) { flags |= SCF_VG; } else if (!strcmp(local_argv[x], "-stop")) { do_kill = SWITCH_TRUE; } else if (!strcmp(local_argv[x], "-nc")) { nc = SWITCH_TRUE; } #ifndef WIN32 else if (!strcmp(local_argv[x], "-ncwait")) { nc = SWITCH_TRUE; do_wait = SWITCH_TRUE; } #endif else if (!strcmp(local_argv[x], "-c")) { nc = SWITCH_FALSE; } else if (!strcmp(local_argv[x], "-conf")) { x++; if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -conf you must specify a config directory\n"); return 255; } SWITCH_GLOBAL_dirs.conf_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.conf_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.conf_dir, local_argv[x]); alt_dirs++; } else if (!strcmp(local_argv[x], "-mod")) { x++; if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -mod you must specify a module directory\n"); return 255; } SWITCH_GLOBAL_dirs.mod_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.mod_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.mod_dir, local_argv[x]); } else if (!strcmp(local_argv[x], "-log")) { x++; if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -log you must specify a log directory\n"); return 255; } SWITCH_GLOBAL_dirs.log_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.log_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.log_dir, local_argv[x]); alt_dirs++; log_set = SWITCH_TRUE; } else if (!strcmp(local_argv[x], "-run")) { x++; if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -run you must specify a pid directory\n"); return 255; } SWITCH_GLOBAL_dirs.run_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.run_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.run_dir, local_argv[x]); run_set = SWITCH_TRUE; } else if (!strcmp(local_argv[x], "-db")) { x++; if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -db you must specify a db directory\n"); return 255; } SWITCH_GLOBAL_dirs.db_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.db_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.db_dir, local_argv[x]); alt_dirs++; } else if (!strcmp(local_argv[x], "-scripts")) { x++; if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -scripts you must specify a scripts directory\n"); return 255; } SWITCH_GLOBAL_dirs.script_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.script_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.script_dir, local_argv[x]); } else if (!strcmp(local_argv[x], "-htdocs")) { x++; if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -htdocs you must specify a htdocs directory\n"); return 255; } SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.htdocs_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.htdocs_dir, local_argv[x]); } else if (!strcmp(local_argv[x], "-base")) { x++; if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -base you must specify a base directory\n"); return 255; } SWITCH_GLOBAL_dirs.base_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.base_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.base_dir, local_argv[x]); } else if (!strcmp(local_argv[x], "-temp")) { x++; if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -temp you must specify a temp directory\n"); return 255; } SWITCH_GLOBAL_dirs.temp_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.temp_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.temp_dir, local_argv[x]); } else if (!strcmp(local_argv[x], "-storage")) { x++; if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -storage you must specify a storage directory\n"); return 255; } SWITCH_GLOBAL_dirs.storage_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.storage_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.storage_dir, local_argv[x]); } else if (!strcmp(local_argv[x], "-recordings")) { x++; if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -recordings you must specify a recording directory\n"); return 255; } SWITCH_GLOBAL_dirs.recordings_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.recordings_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.recordings_dir, local_argv[x]); } else if (!strcmp(local_argv[x], "-grammar")) { x++; if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -grammar you must specify a grammar directory\n"); return 255; } SWITCH_GLOBAL_dirs.grammar_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.grammar_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.grammar_dir, local_argv[x]); } else if (!strcmp(local_argv[x], "-sounds")) { x++; if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -sounds you must specify a sounds directory\n"); return 255; } SWITCH_GLOBAL_dirs.sounds_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.sounds_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.sounds_dir, local_argv[x]); } else if (!strcmp(local_argv[x], "-cfgname")) { x++; if (switch_strlen_zero(local_argv[x]) || is_option(local_argv[x])) { fprintf(stderr, "When using -cfgname you must specify a filename\n"); return 255; } SWITCH_GLOBAL_filenames.conf_name = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_filenames.conf_name) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_filenames.conf_name, local_argv[x]); } /* Unknown option (always last!) */ else { fprintf(stderr, "Unknown option '%s', see '%s -help' for a list of valid options\n", local_argv[x], local_argv[0]); exit(EXIT_FAILURE); } } if (log_set && !run_set) { SWITCH_GLOBAL_dirs.run_dir = (char *) malloc(strlen(SWITCH_GLOBAL_dirs.log_dir) + 1); if (!SWITCH_GLOBAL_dirs.run_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.run_dir, SWITCH_GLOBAL_dirs.log_dir); } if (do_kill) { return freeswitch_kill_background(); } if (apr_initialize() != SWITCH_STATUS_SUCCESS) { fprintf(stderr, "FATAL ERROR! Could not initialize APR\n"); return 255; } if (alt_dirs && alt_dirs != 3) { fprintf(stderr, "You must specify all or none of -conf, -log, and -db\n"); return 255; } #ifndef FS_64BIT #if defined(HAVE_SETRLIMIT) && !defined(__sun) if (!waste && !(flags & SCF_VG)) { struct rlimit rlp; memset(&rlp, 0, sizeof(rlp)); getrlimit(RLIMIT_STACK, &rlp); if (rlp.rlim_cur != SWITCH_THREAD_STACKSIZE) { char buf[1024] = ""; int i = 0; memset(&rlp, 0, sizeof(rlp)); rlp.rlim_cur = SWITCH_THREAD_STACKSIZE; rlp.rlim_max = SWITCH_SYSTEM_THREAD_STACKSIZE; setrlimit(RLIMIT_STACK, &rlp); apr_terminate(); ret = (int) execv(argv[0], argv); for (i = 0; i < argc; i++) { switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s ", argv[i]); } return system(buf); } } #endif #endif signal(SIGILL, handle_SIGILL); signal(SIGTERM, handle_SIGILL); #ifndef WIN32 if (do_wait) { if (pipe(fds)) { fprintf(stderr, "System Error!\n"); exit(-1); } signal(SIGCHLD, handle_SIGCHLD); } #endif if (nc) { #ifdef WIN32 FreeConsole(); #else if (!nf) { daemonize(do_wait ? fds : NULL); } #endif } switch (priority) { case 2: set_realtime_priority(); break; case 1: set_normal_priority(); break; case -1: set_low_priority(); break; default: set_auto_priority(); break; } switch_core_setrlimits(); #ifndef WIN32 if (runas_user || runas_group) { if (change_user_group(runas_user, runas_group) < 0) { fprintf(stderr, "Failed to switch user [%s] / group [%s]\n", switch_strlen_zero(runas_user) ? "-" : runas_user, switch_strlen_zero(runas_group) ? "-" : runas_group); return 255; } } #else if (win32_service) { /* Attempt to start service */ SERVICE_TABLE_ENTRY dispatchTable[] = { {service_name, &service_main} , {NULL, NULL} }; service_flags = flags; /* copy parsed flags for service startup */ if (StartServiceCtrlDispatcher(dispatchTable) == 0) { /* Not loaded as a service */ fprintf(stderr, "Error Freeswitch loaded as a console app with -service option\n"); fprintf(stderr, "To install the service load freeswitch with -install\n"); } exit(EXIT_SUCCESS); } #endif switch_core_set_globals(); pid = getpid(); memset(pid_buffer, 0, sizeof(pid_buffer)); switch_snprintf(pid_path, sizeof(pid_path), "%s%s%s", SWITCH_GLOBAL_dirs.run_dir, SWITCH_PATH_SEPARATOR, pfile); switch_snprintf(pid_buffer, sizeof(pid_buffer), "%d", pid); pid_len = strlen(pid_buffer); apr_pool_create(&pool, NULL); switch_dir_make_recursive(SWITCH_GLOBAL_dirs.run_dir, SWITCH_DEFAULT_DIR_PERMS, pool); if (switch_file_open(&fd, pid_path, SWITCH_FOPEN_READ, SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE, pool) == SWITCH_STATUS_SUCCESS) { old_pid_len = sizeof(old_pid_buffer); switch_file_read(fd, old_pid_buffer, &old_pid_len); switch_file_close(fd); } if (switch_file_open(&fd, pid_path, SWITCH_FOPEN_WRITE | SWITCH_FOPEN_CREATE | SWITCH_FOPEN_TRUNCATE, SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE, pool) != SWITCH_STATUS_SUCCESS) { fprintf(stderr, "Cannot open pid file %s.\n", pid_path); return 255; } if (switch_file_lock(fd, SWITCH_FLOCK_EXCLUSIVE | SWITCH_FLOCK_NONBLOCK) != SWITCH_STATUS_SUCCESS) { fprintf(stderr, "Cannot lock pid file %s.\n", pid_path); old_pid_len = strlen(old_pid_buffer); if (strlen(old_pid_buffer)) { switch_file_write(fd, old_pid_buffer, &old_pid_len); } return 255; } switch_file_write(fd, pid_buffer, &pid_len); if (switch_core_init_and_modload(flags, nc ? SWITCH_FALSE : SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) { fprintf(stderr, "Cannot Initialize [%s]\n", err); return 255; } #ifndef WIN32 if (do_wait) { if (fds[1] > -1) { int i, v = 1; if ((i = write(fds[1], &v, sizeof(v))) < 0) { fprintf(stderr, "System Error [%s]\n", strerror(errno)); } else { i = read(fds[1], &v, sizeof(v)); } shutdown(fds[1], 2); close(fds[1]); fds[1] = -1; } } #endif switch_core_runtime_loop(nc); destroy_status = switch_core_destroy(); switch_file_close(fd); apr_pool_destroy(pool); if (unlink(pid_path) != 0) { fprintf(stderr, "Failed to delete pid file [%s]\n", pid_path); } if (destroy_status == SWITCH_STATUS_RESTART) { char buf[1024] = ""; int j = 0; switch_sleep(1000000); ret = (int) execv(argv[0], argv); fprintf(stderr, "Restart Failed [%s] resorting to plan b\n", strerror(errno)); for (j = 0; j < argc; j++) { switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s ", argv[j]); } ret = system(buf); } return ret; }
/* the main application entry point */ int main(int argc, char *argv[]) { char pid_path[256] = ""; /* full path to the pid file */ char pid_buffer[32] = ""; /* pid string */ char old_pid_buffer[32] = ""; /* pid string */ switch_size_t pid_len, old_pid_len; const char *err = NULL; /* error value for return from freeswitch initialization */ #ifndef WIN32 int nf = 0; /* TRUE if we are running in nofork mode */ char *runas_user = NULL; char *runas_group = NULL; #else int win32_service = 0; #endif int nc = 0; /* TRUE if we are running in noconsole mode */ pid_t pid = 0; int i, x; char *opts; char opts_str[1024] = ""; char *local_argv[1024] = { 0 }; int local_argc = argc; char *arg_argv[128] = { 0 }; char *usageDesc; int alt_dirs = 0, log_set = 0, run_set = 0, kill = 0; int known_opt; int high_prio = 0; #ifdef __sun switch_core_flag_t flags = SCF_USE_SQL; #else switch_core_flag_t flags = SCF_USE_SQL | SCF_USE_AUTO_NAT | SCF_CALIBRATE_CLOCK | SCF_USE_CLOCK_RT; #endif int ret = 0; switch_status_t destroy_status; switch_file_t *fd; switch_memory_pool_t *pool = NULL; #ifdef HAVE_SETRLIMIT struct rlimit rlp; int waste = 0; #endif for (x = 0; x < argc; x++) { local_argv[x] = argv[x]; } if ((opts = getenv("FREESWITCH_OPTS"))) { strncpy(opts_str, opts, sizeof(opts_str) - 1); i = switch_separate_string(opts_str, ' ', arg_argv, (sizeof(arg_argv) / sizeof(arg_argv[0]))); for (x = 0; x < i; x++) { local_argv[local_argc++] = arg_argv[x]; } } if (local_argv[0] && strstr(local_argv[0], "freeswitchd")) { nc++; } usageDesc = "these are the optional arguments you can pass to freeswitch\n" #ifdef WIN32 "\t-service [name] -- start freeswitch as a service, cannot be used if loaded as a console app\n" "\t-install [name] -- install freeswitch as a service, with optional service name\n" "\t-uninstall -- remove freeswitch as a service\n" #else "\t-nf -- no forking\n" "\t-u [user] -- specify user to switch to\n" "\t-g [group] -- specify group to switch to\n" #endif "\t-help -- this message\n" "\t-version -- print the version and exit\n" #ifdef HAVE_SETRLIMIT "\t-waste -- allow memory waste\n" "\t-core -- dump cores\n" #endif "\t-hp -- enable high priority settings\n" "\t-vg -- run under valgrind\n" "\t-nosql -- disable internal sql scoreboard\n" "\t-heavy-timer -- Heavy Timer, possibly more accurate but at a cost\n" "\t-nonat -- disable auto nat detection\n" "\t-nocal -- disable clock calibration\n" "\t-nort -- disable clock clock_realtime\n" "\t-stop -- stop freeswitch\n" "\t-nc -- do not output to a console and background\n" "\t-c -- output to a console and stay in the foreground\n" "\t-conf [confdir] -- specify an alternate config dir\n" "\t-log [logdir] -- specify an alternate log dir\n" "\t-run [rundir] -- specify an alternate run dir\n" "\t-db [dbdir] -- specify an alternate db dir\n" "\t-mod [moddir] -- specify an alternate mod dir\n" "\t-htdocs [htdocsdir] -- specify an alternate htdocs dir\n" "\t-scripts [scriptsdir] -- specify an alternate scripts dir\n"; for (x = 1; x < local_argc; x++) { known_opt = 0; #ifdef WIN32 if (x == 1) { if (local_argv[x] && !strcmp(local_argv[x], "-service")) { /* New installs will always have the service name specified, but keep a default for compat */ x++; if (local_argv[x] && strlen(local_argv[x])) { switch_copy_string(service_name, local_argv[x], SERVICENAME_MAXLEN); } else { switch_copy_string(service_name, SERVICENAME_DEFAULT, SERVICENAME_MAXLEN); } known_opt++; win32_service++; continue; } if (local_argv[x] && !strcmp(local_argv[x], "-install")) { char exePath[1024]; char servicePath[1024]; x++; if (local_argv[x] && strlen(local_argv[x])) { switch_copy_string(service_name, local_argv[x], SERVICENAME_MAXLEN); } else { switch_copy_string(service_name, SERVICENAME_DEFAULT, SERVICENAME_MAXLEN); } known_opt++; GetModuleFileName(NULL, exePath, 1024); snprintf(servicePath, sizeof(servicePath), "%s -service %s", exePath, service_name); { /* Perform service installation */ SC_HANDLE hService; SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (!hSCManager) { fprintf(stderr, "Could not open service manager (%d).\n", GetLastError()); exit(1); } hService = CreateService(hSCManager, service_name, service_name, GENERIC_READ | GENERIC_EXECUTE | SERVICE_CHANGE_CONFIG, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, servicePath, NULL, NULL, NULL, NULL, /* Service start name */ NULL); if (!hService) { fprintf(stderr, "Error creating freeswitch service (%d).\n", GetLastError()); } else { /* Set desc, and don't care if it succeeds */ SERVICE_DESCRIPTION desc; desc.lpDescription = "The FreeSWITCH service."; if (!ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &desc)) { fprintf(stderr, "FreeSWITCH installed, but could not set the service description (%d).\n", GetLastError()); } CloseServiceHandle(hService); } CloseServiceHandle(hSCManager); exit(0); } } if (local_argv[x] && !strcmp(local_argv[x], "-uninstall")) { x++; if (local_argv[x] && strlen(local_argv[x])) { switch_copy_string(service_name, local_argv[x], SERVICENAME_MAXLEN); } else { switch_copy_string(service_name, SERVICENAME_DEFAULT, SERVICENAME_MAXLEN); } { /* Do the uninstallation */ SC_HANDLE hService; SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (!hSCManager) { fprintf(stderr, "Could not open service manager (%d).\n", GetLastError()); exit(1); } hService = OpenService(hSCManager, service_name, DELETE); known_opt++; if (hService != NULL) { /* remove the service! */ if (!DeleteService(hService)) { fprintf(stderr, "Error deleting service (%d).\n", GetLastError()); } CloseServiceHandle(hService); } else { fprintf(stderr, "Error opening service (%d).\n", GetLastError()); } CloseServiceHandle(hSCManager); exit(0); } } } #else if (local_argv[x] && !strcmp(local_argv[x], "-u")) { x++; if (local_argv[x] && strlen(local_argv[x])) { runas_user = local_argv[x]; } known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-g")) { x++; if (local_argv[x] && strlen(local_argv[x])) { runas_group = local_argv[x]; } known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-nf")) { nf++; known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-version")) { fprintf(stdout, "FreeSWITCH version: %s\n", SWITCH_VERSION_FULL); return 0; known_opt++; } #endif #ifdef HAVE_SETRLIMIT if (local_argv[x] && !strcmp(local_argv[x], "-core")) { memset(&rlp, 0, sizeof(rlp)); rlp.rlim_cur = RLIM_INFINITY; rlp.rlim_max = RLIM_INFINITY; setrlimit(RLIMIT_CORE, &rlp); known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-waste")) { waste++; known_opt++; } #endif if (local_argv[x] && !strcmp(local_argv[x], "-hp")) { high_prio++; known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-nosql")) { flags &= ~SCF_USE_SQL; known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-nonat")) { flags &= ~SCF_USE_AUTO_NAT; known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-heavy-timer")) { flags |= SCF_USE_HEAVY_TIMING; known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-nort")) { flags &= ~SCF_USE_CLOCK_RT; known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-nocal")) { flags &= ~SCF_CALIBRATE_CLOCK; known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-vg")) { flags |= SCF_VG; known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-stop")) { kill++; known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-nc")) { nc++; known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-c")) { nc = 0; known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-conf")) { x++; if (local_argv[x] && strlen(local_argv[x])) { SWITCH_GLOBAL_dirs.conf_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.conf_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.conf_dir, local_argv[x]); alt_dirs++; } else { fprintf(stderr, "When using -conf you must specify a config directory\n"); return 255; } known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-mod")) { x++; if (local_argv[x] && strlen(local_argv[x])) { SWITCH_GLOBAL_dirs.mod_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.mod_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.mod_dir, local_argv[x]); } else { fprintf(stderr, "When using -mod you must specify a module directory\n"); return 255; } known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-log")) { x++; if (local_argv[x] && strlen(local_argv[x])) { SWITCH_GLOBAL_dirs.log_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.log_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.log_dir, local_argv[x]); alt_dirs++; log_set++; } else { fprintf(stderr, "When using -log you must specify a log directory\n"); return 255; } known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-run")) { x++; if (local_argv[x] && strlen(local_argv[x])) { SWITCH_GLOBAL_dirs.run_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.run_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.run_dir, local_argv[x]); run_set++; } else { fprintf(stderr, "When using -run you must specify a pid directory\n"); return 255; } known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-db")) { x++; if (local_argv[x] && strlen(local_argv[x])) { SWITCH_GLOBAL_dirs.db_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.db_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.db_dir, local_argv[x]); alt_dirs++; } else { fprintf(stderr, "When using -db you must specify a db directory\n"); return 255; } known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-scripts")) { x++; if (local_argv[x] && strlen(local_argv[x])) { SWITCH_GLOBAL_dirs.script_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.script_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.script_dir, local_argv[x]); } else { fprintf(stderr, "When using -scripts you must specify a scripts directory\n"); return 255; } known_opt++; } if (local_argv[x] && !strcmp(local_argv[x], "-htdocs")) { x++; if (local_argv[x] && strlen(local_argv[x])) { SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(strlen(local_argv[x]) + 1); if (!SWITCH_GLOBAL_dirs.htdocs_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.htdocs_dir, local_argv[x]); } else { fprintf(stderr, "When using -htdocs you must specify a htdocs directory\n"); return 255; } known_opt++; } if (!known_opt || (local_argv[x] && (!strcmp(local_argv[x], "-help") || !strcmp(local_argv[x], "-h") || !strcmp(local_argv[x], "-?")))) { printf("%s\n", usageDesc); exit(0); } } if (log_set && !run_set) { SWITCH_GLOBAL_dirs.run_dir = (char *) malloc(strlen(SWITCH_GLOBAL_dirs.log_dir) + 1); if (!SWITCH_GLOBAL_dirs.run_dir) { fprintf(stderr, "Allocation error\n"); return 255; } strcpy(SWITCH_GLOBAL_dirs.run_dir, SWITCH_GLOBAL_dirs.log_dir); } if (kill) { return freeswitch_kill_background(); } if (apr_initialize() != SWITCH_STATUS_SUCCESS) { fprintf(stderr, "FATAL ERROR! Could not initialize APR\n"); return 255; } if (alt_dirs && alt_dirs != 3) { fprintf(stderr, "You must specify all or none of -conf, -log, and -db\n"); return 255; } signal(SIGILL, handle_SIGILL); signal(SIGTERM, handle_SIGILL); if (nc) { #ifdef WIN32 FreeConsole(); #else if (!nf) { daemonize(); } #endif } #if defined(HAVE_SETRLIMIT) && !defined(__sun) if (!waste && !(flags & SCF_VG)) { memset(&rlp, 0, sizeof(rlp)); getrlimit(RLIMIT_STACK, &rlp); if (rlp.rlim_max > SWITCH_THREAD_STACKSIZE) { char buf[1024] = ""; int i = 0; fprintf(stderr, "Error: stacksize %d is too large: run ulimit -s %d or run %s -waste.\nauto-adjusting stack size for optimal performance...\n", (int) (rlp.rlim_max / 1024), SWITCH_THREAD_STACKSIZE / 1024, local_argv[0]); memset(&rlp, 0, sizeof(rlp)); rlp.rlim_cur = SWITCH_THREAD_STACKSIZE; rlp.rlim_max = SWITCH_THREAD_STACKSIZE; setrlimit(RLIMIT_STACK, &rlp); apr_terminate(); ret = (int) execv(argv[0], argv); for (i = 0; i < argc; i++) { switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s ", argv[i]); } return system(buf); } } #endif if (high_prio) { set_high_priority(); } switch_core_setrlimits(); #ifndef WIN32 if (runas_user || runas_group) { if (change_user_group(runas_user, runas_group) < 0) { fprintf(stderr, "Failed to switch user / group\n"); return 255; } } #else if (win32_service) { { /* Attempt to start service */ SERVICE_TABLE_ENTRY dispatchTable[] = { {service_name, &service_main} , {NULL, NULL} }; if (StartServiceCtrlDispatcher(dispatchTable) == 0) { /* Not loaded as a service */ fprintf(stderr, "Error Freeswitch loaded as a console app with -service option\n"); fprintf(stderr, "To install the service load freeswitch with -install\n"); } exit(0); } } #endif switch_core_set_globals(); pid = getpid(); memset(pid_buffer, 0, sizeof(pid_buffer)); switch_snprintf(pid_path, sizeof(pid_path), "%s%s%s", SWITCH_GLOBAL_dirs.run_dir, SWITCH_PATH_SEPARATOR, pfile); switch_snprintf(pid_buffer, sizeof(pid_buffer), "%d", pid); pid_len = strlen(pid_buffer); apr_pool_create(&pool, NULL); switch_dir_make_recursive(SWITCH_GLOBAL_dirs.run_dir, SWITCH_DEFAULT_DIR_PERMS, pool); if (switch_file_open(&fd, pid_path, SWITCH_FOPEN_READ, SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE, pool) == SWITCH_STATUS_SUCCESS) { old_pid_len = sizeof(old_pid_buffer); switch_file_read(fd, old_pid_buffer, &old_pid_len); switch_file_close(fd); } if (switch_file_open(&fd, pid_path, SWITCH_FOPEN_WRITE | SWITCH_FOPEN_CREATE | SWITCH_FOPEN_TRUNCATE, SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE, pool) != SWITCH_STATUS_SUCCESS) { fprintf(stderr, "Cannot open pid file %s.\n", pid_path); return 255; } if (switch_file_lock(fd, SWITCH_FLOCK_EXCLUSIVE | SWITCH_FLOCK_NONBLOCK) != SWITCH_STATUS_SUCCESS) { fprintf(stderr, "Cannot lock pid file %s.\n", pid_path); old_pid_len = strlen(old_pid_buffer); if (strlen(old_pid_buffer)) { switch_file_write(fd, old_pid_buffer, &old_pid_len); } return 255; } switch_file_write(fd, pid_buffer, &pid_len); if (switch_core_init_and_modload(flags, nc ? SWITCH_FALSE : SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) { fprintf(stderr, "Cannot Initialize [%s]\n", err); return 255; } switch_core_runtime_loop(nc); destroy_status = switch_core_destroy(); switch_file_close(fd); if (unlink(pid_path) != 0) { fprintf(stderr, "Failed to delete pid file [%s]\n", pid_path); } if (destroy_status == SWITCH_STATUS_RESTART) { char buf[1024] = ""; int j = 0; switch_sleep(1000000); ret = (int) execv(argv[0], argv); fprintf(stderr, "Restart Failed [%s] resorting to plan b\n", strerror(errno)); for (j = 0; j < argc; j++) { switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s ", argv[j]); } ret = system(buf); } return ret; }
static void eval_some_python(const char *funcname, char *args, switch_core_session_t *session, switch_stream_handle_t *stream, switch_event_t *params, char **str, struct switch_py_thread *pt) { PyThreadState *tstate = NULL; char *dupargs = NULL; char *argv[2] = { 0 }; int argc; char *script = NULL; PyObject *module = NULL, *sp = NULL, *stp = NULL, *eve = NULL; PyObject *function = NULL; PyObject *arg = NULL; PyObject *result = NULL; char *p; if (str) { *str = NULL; } if (args) { dupargs = strdup(args); } else { return; } assert(dupargs != NULL); if (!(argc = switch_separate_string(dupargs, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No module name specified!\n"); goto done; } script = strdup(switch_str_nil(argv[0])); if ((p = strstr(script, "::"))) { *p = '\0'; p += 2; if (p) { funcname = p; } } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Invoking py module: %s\n", script); tstate = PyThreadState_New(mainThreadState->interp); if (!tstate) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error acquiring tstate\n"); goto done; } /* Save state in thread struct so we can terminate it later if needed */ if (pt) pt->tstate = tstate; // swap in thread state PyEval_AcquireThread(tstate); init_freeswitch(); // import the module module = PyImport_ImportModule((char *) script); if (!module) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error importing module\n"); PyErr_Print(); PyErr_Clear(); goto done_swap_out; } // reload the module module = PyImport_ReloadModule(module); if (!module) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error reloading module\n"); PyErr_Print(); PyErr_Clear(); goto done_swap_out; } // get the handler function to be called function = PyObject_GetAttrString(module, (char *) funcname); if (!function) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Module does not define %s\n", funcname); PyErr_Print(); PyErr_Clear(); goto done_swap_out; } if (session) { sp = mod_python_conjure_session(module, session); } if (params) { eve = mod_python_conjure_event(params); } if (stream) { stp = mod_python_conjure_stream(stream); if (stream->param_event) { eve = mod_python_conjure_event(stream->param_event); } } if (sp && eve && stp) { arg = Py_BuildValue("(OOOs)", sp, stp, eve, switch_str_nil(argv[1])); } else if (eve && stp) { arg = Py_BuildValue("(sOOs)", "na", stp, eve, switch_str_nil(argv[1])); } else if (eve) { arg = Py_BuildValue("(Os)", eve, switch_str_nil(argv[1])); } else if (sp) { arg = Py_BuildValue("(Os)", sp, switch_str_nil(argv[1])); } else { arg = Py_BuildValue("(s)", switch_str_nil(argv[1])); } // invoke the handler switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call python script \n"); result = PyEval_CallObjectWithKeywords(function, arg, (PyObject *) NULL); Py_DECREF(function); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Finished calling python script \n"); // check the result and print out any errors if (result) { if (str) { *str = strdup((char *) PyString_AsString(result)); } } else if (!PyErr_ExceptionMatches(PyExc_SystemExit)) { // Print error, but ignore SystemExit switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error calling python script\n"); PyErr_Print(); PyErr_Clear(); PyRun_SimpleString("python_makes_sense"); PyGC_Collect(); } done_swap_out: if (arg) { Py_DECREF(arg); } if (sp) { Py_DECREF(sp); } if (tstate) { // thread state must be cleared explicitly or we'll get memory leaks PyThreadState_Clear(tstate); PyEval_ReleaseThread(tstate); PyThreadState_Delete(tstate); } done: switch_safe_free(dupargs); switch_safe_free(script); }
static void launch_thread(const char *name, const char *path, switch_xml_t directory) { local_stream_source_t *source = NULL; switch_memory_pool_t *pool; switch_xml_t param; switch_thread_t *thread; switch_threadattr_t *thd_attr = NULL; if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n"); abort(); } source = switch_core_alloc(pool, sizeof(*source)); assert(source != NULL); source->pool = pool; source->name = switch_core_strdup(source->pool, name); source->location = switch_core_strdup(source->pool, path); source->rate = 8000; source->interval = 20; source->channels = 1; source->timer_name = "soft"; source->prebuf = DEFAULT_PREBUFFER_SIZE; source->stopped = 0; source->hup = 0; source->chime_freq = 30; for (param = switch_xml_child(directory, "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, "rate")) { int tmp = atoi(val); if (tmp == 8000 || tmp == 12000 || tmp == 16000 || tmp == 24000 || tmp == 32000 || tmp == 48000) { source->rate = tmp; } } else if (!strcasecmp(var, "shuffle")) { source->shuffle = switch_true(val); } else if (!strcasecmp(var, "prebuf")) { int tmp = atoi(val); if (tmp > 0) { source->prebuf = (uint32_t) tmp; } } else if (!strcasecmp(var, "channels")) { int tmp = atoi(val); if (tmp == 1 || tmp == 2) { source->channels = (uint8_t) tmp; } } else if (!strcasecmp(var, "chime-freq")) { int tmp = atoi(val); if (tmp > 1) { source->chime_freq = tmp; } } else if (!strcasecmp(var, "chime-max")) { int tmp = atoi(val); if (tmp > 1) { source->chime_max = tmp; } } else if (!strcasecmp(var, "chime-list")) { char *list_dup = switch_core_strdup(source->pool, val); source->chime_total = switch_separate_string(list_dup, ',', source->chime_list, (sizeof(source->chime_list) / sizeof(source->chime_list[0]))); } else if (!strcasecmp(var, "interval")) { int tmp = atoi(val); if (SWITCH_ACCEPTABLE_INTERVAL(tmp)) { source->interval = tmp; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Interval must be multiple of 10 and less than %d, Using default of 20\n", SWITCH_MAX_INTERVAL); } } else if (!strcasecmp(var, "timer-name")) { source->timer_name = switch_core_strdup(source->pool, val); } } if (source->chime_max) { source->chime_max *= source->rate; } if (source->chime_total) { source->chime_counter = source->rate * source->chime_freq; } source->samples = switch_samples_per_packet(source->rate, source->interval); switch_mutex_init(&source->mutex, SWITCH_MUTEX_NESTED, source->pool); switch_threadattr_create(&thd_attr, source->pool); switch_threadattr_detach_set(thd_attr, 1); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); switch_thread_create(&thread, thd_attr, read_stream_thread, source, source->pool); }
static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void *obj) { local_stream_source_t *source = obj; switch_file_handle_t fh = { 0 }; local_stream_context_t *cp; char file_buf[128] = "", path_buf[512] = ""; switch_timer_t timer = { 0 }; int fd = -1; switch_buffer_t *audio_buffer; switch_byte_t *dist_buf; switch_size_t used; int skip = 0; switch_memory_pool_t *temp_pool = NULL; switch_mutex_lock(globals.mutex); THREADS++; switch_mutex_unlock(globals.mutex); if (!source->prebuf) { source->prebuf = DEFAULT_PREBUFFER_SIZE; } switch_buffer_create_dynamic(&audio_buffer, 1024, source->prebuf + 10, 0); dist_buf = switch_core_alloc(source->pool, source->prebuf + 10); if (source->shuffle) { skip = do_rand(); } switch_thread_rwlock_create(&source->rwlock, source->pool); if (RUNNING) { switch_mutex_lock(globals.mutex); switch_core_hash_insert(globals.source_hash, source->name, source); switch_mutex_unlock(globals.mutex); source->ready = 1; } while (RUNNING && !source->stopped) { const char *fname; if (temp_pool) { switch_core_destroy_memory_pool(&temp_pool); } if (switch_core_new_memory_pool(&temp_pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error creating pool"); goto done; } if (switch_dir_open(&source->dir_handle, source->location, temp_pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Can't open directory: %s\n", source->location); goto done; } switch_yield(1000000); while (RUNNING && !source->stopped) { switch_size_t olen; uint8_t abuf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 }; if (fd > -1) { char *p; if (switch_fd_read_line(fd, path_buf, sizeof(path_buf))) { if ((p = strchr(path_buf, '\r')) || (p = strchr(path_buf, '\n'))) { *p = '\0'; } } else { close(fd); fd = -1; continue; } } else { if (!(fname = switch_dir_next_file(source->dir_handle, file_buf, sizeof(file_buf)))) { break; } switch_snprintf(path_buf, sizeof(path_buf), "%s%s%s", source->location, SWITCH_PATH_SEPARATOR, fname); if (switch_stristr(".loc", path_buf)) { if ((fd = open(path_buf, O_RDONLY)) < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", fname); switch_yield(1000000); } continue; } } if (skip > 0) { skip--; continue; } fname = path_buf; fh.prebuf = source->prebuf; fh.pre_buffer_datalen = source->prebuf; if (switch_core_file_open(&fh, (char *) fname, source->channels, source->rate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", fname); switch_yield(1000000); continue; } if (switch_core_timer_init(&timer, source->timer_name, source->interval, (int)source->samples, temp_pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Can't start timer.\n"); switch_dir_close(source->dir_handle); source->dir_handle = NULL; goto done; } while (RUNNING && !source->stopped) { int is_open; switch_file_handle_t *use_fh = &fh; switch_core_timer_next(&timer); olen = source->samples; if (source->chime_total) { if (source->chime_counter > 0) { source->chime_counter -= (int32_t)source->samples; } if (!switch_test_flag((&source->chime_fh), SWITCH_FILE_OPEN) && source->chime_counter <= 0) { char *val; val = source->chime_list[source->chime_cur++]; if (source->chime_cur >= source->chime_total) { source->chime_cur = 0; } if (switch_core_file_open(&source->chime_fh, (char *) val, source->channels, source->rate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", val); } } if (switch_test_flag((&source->chime_fh), SWITCH_FILE_OPEN)) { use_fh = &source->chime_fh; } } retry: is_open = switch_test_flag(use_fh, SWITCH_FILE_OPEN); if (source->hup) { source->hup = 0; if (is_open) { is_open = 0; switch_core_file_close(use_fh); if (use_fh == &source->chime_fh) { source->chime_counter = source->rate * source->chime_freq; use_fh = &fh; goto retry; //switch_core_file_close(&fh); } } } if (is_open) { if (switch_core_file_read(use_fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) { switch_core_file_close(use_fh); if (use_fh == &source->chime_fh) { source->chime_counter = source->rate * source->chime_freq; } is_open = 0; } else { if (use_fh == &source->chime_fh && source->chime_max) { source->chime_max_counter += (int32_t)source->samples; if (source->chime_max_counter >= source->chime_max) { source->chime_max_counter = 0; switch_core_file_close(use_fh); source->chime_counter = source->rate * source->chime_freq; use_fh = &fh; goto retry; } } switch_buffer_write(audio_buffer, abuf, olen * 2); } } used = switch_buffer_inuse(audio_buffer); if (!used && !is_open) { break; } if (!is_open || used >= source->prebuf || (source->total && used > source->samples * 2)) { used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2); if (source->total) { uint32_t bused = 0; switch_mutex_lock(source->mutex); for (cp = source->context_list; cp && RUNNING; cp = cp->next) { if (switch_test_flag(cp->handle, SWITCH_FILE_CALLBACK)) { continue; } switch_mutex_lock(cp->audio_mutex); bused = (uint32_t)switch_buffer_inuse(cp->audio_buffer); if (bused > source->samples * 768) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Flushing Stream Handle Buffer [%s() %s:%d] size: %u samples: %ld\n", cp->func, cp->file, cp->line, bused, (long)source->samples); switch_buffer_zero(cp->audio_buffer); } else { switch_buffer_write(cp->audio_buffer, dist_buf, used); } switch_mutex_unlock(cp->audio_mutex); } switch_mutex_unlock(source->mutex); } } } switch_core_timer_destroy(&timer); if (RUNNING && source->shuffle) { skip = do_rand(); } } switch_dir_close(source->dir_handle); source->dir_handle = NULL; if (source->full_reload) { if (source->rwlock && switch_thread_rwlock_trywrlock(source->rwlock) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Cannot stop local_stream://%s because it is in use.\n",source->name); if (source->part_reload) { switch_xml_t cfg, xml, directory, param; if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf); } if ((directory = switch_xml_find_child(cfg, "directory", "name", source->name))) { for (param = switch_xml_child(directory, "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, "shuffle")) { source->shuffle = switch_true(val); } else if (!strcasecmp(var, "chime-freq")) { int tmp = atoi(val); if (tmp > 1) { source->chime_freq = tmp; } } else if (!strcasecmp(var, "chime-max")) { int tmp = atoi(val); if (tmp > 1) { source->chime_max = tmp; } } else if (!strcasecmp(var, "chime-list")) { char *list_dup = switch_core_strdup(source->pool, val); source->chime_total = switch_separate_string(list_dup, ',', source->chime_list, (sizeof(source->chime_list) / sizeof(source->chime_list[0]))); } else if (!strcasecmp(var, "interval")) { int tmp = atoi(val); if (SWITCH_ACCEPTABLE_INTERVAL(tmp)) { source->interval = tmp; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Interval must be multiple of 10 and less than %d, Using default of 20\n", SWITCH_MAX_INTERVAL); } } if (source->chime_max) { source->chime_max *= source->rate; } if (source->chime_total) { source->chime_counter = source->rate * source->chime_freq; } } } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "local_stream://%s partially reloaded.\n",source->name); source->part_reload = 0; } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "local_stream://%s fully reloaded.\n",source->name); launch_streams(source->name); goto done; } } } done: if (switch_test_flag((&fh), SWITCH_FILE_OPEN)) { switch_core_file_close(&fh); } if (switch_test_flag((&source->chime_fh), SWITCH_FILE_OPEN)) { switch_core_file_close(&source->chime_fh); } source->ready = 0; switch_mutex_lock(globals.mutex); switch_core_hash_delete(globals.source_hash, source->name); switch_mutex_unlock(globals.mutex); switch_thread_rwlock_wrlock(source->rwlock); switch_thread_rwlock_unlock(source->rwlock); switch_buffer_destroy(&audio_buffer); if (fd > -1) { close(fd); } if (temp_pool) { switch_core_destroy_memory_pool(&temp_pool); } switch_core_destroy_memory_pool(&source->pool); switch_mutex_lock(globals.mutex); THREADS--; switch_mutex_unlock(globals.mutex); return NULL; }
static switch_status_t enum_lookup(char *root, char *in, enum_record_t **results, switch_channel_t *channel, switch_core_session_t *session) { switch_status_t sstatus = SWITCH_STATUS_SUCCESS; char *mnum = NULL, *mroot = NULL, *p; char *server[ENUM_MAXNAMESERVERS]; int inameserver = 0; char *argv[ ENUM_MAXNAMESERVERS ] = { 0 }; int argc; int x = 0; char *enum_nameserver_dup; const char *enum_nameserver = NULL; *results = NULL; mnum = switch_mprintf("%s%s", *in == '+' ? "" : "+", in); if ((p = strchr(mnum, '*'))) { *p++ = '\0'; mroot = switch_mprintf("%s.%s", p, root ? root : globals.isn_root); root = mroot; } if (zstr(root)) { root = globals.root; } /* Empty the server array */ for(inameserver=0; inameserver<ENUM_MAXNAMESERVERS; inameserver++) { server[inameserver] = NULL; } inameserver = 0; /* check for enum_nameserver channel var */ if (channel) { enum_nameserver = switch_channel_get_variable(channel, "enum_nameserver"); } if (zstr(enum_nameserver)) { enum_nameserver = switch_core_get_variable("enum-server"); } if (!zstr(enum_nameserver)) { /* Blank the server array */ for(inameserver=0; inameserver<ENUM_MAXNAMESERVERS; inameserver++) { server[inameserver] = NULL; } enum_nameserver_dup = switch_core_session_strdup(session, enum_nameserver); argc = switch_separate_string(enum_nameserver_dup, ',', argv, (sizeof(argv) / sizeof(argv[0]))); inameserver = 0; for (x = 0; x < argc; x++) { server[inameserver] = argv[x]; inameserver++; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Enum nameserver override : %s\n", enum_nameserver); } if (!inameserver) { /* use config param "nameserver" ( can be up to ENUM_MAXNAMESERVERS ) */ for(inameserver = 0; inameserver<ENUM_MAXNAMESERVERS; inameserver++) { server[inameserver] = NULL; if ( globals.nameserver[inameserver] != NULL ) { server[inameserver] = globals.nameserver[inameserver]; } } } ldns_lookup(mnum, root, server, results); switch_safe_free(mnum); switch_safe_free(mroot); return sstatus; }
// This function and do_lookup_url functions could possibly be merged together. Or at least have do_lookup_url call this up as part of the initialization routine as it is a subset of the operations. static void http_sendfile_initialize_curl(http_sendfile_data_t *http_data) { uint8_t count; http_data->curl_handle = curl_easy_init(); if (!strncasecmp(http_data->url, "https", 5)) { curl_easy_setopt(http_data->curl_handle, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(http_data->curl_handle, CURLOPT_SSL_VERIFYHOST, 0); } /* From the docs: * Optionally, you can provide data to POST using the CURLOPT_READFUNCTION and CURLOPT_READDATA * options but then you must make sure to not set CURLOPT_POSTFIELDS to anything but NULL * curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, strlen(data)); * curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, (void *) data); */ // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Post data: %s\n", data); curl_easy_setopt(http_data->curl_handle, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(http_data->curl_handle, CURLOPT_MAXREDIRS, 15); curl_easy_setopt(http_data->curl_handle, CURLOPT_URL, http_data->url); curl_easy_setopt(http_data->curl_handle, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(http_data->curl_handle, CURLOPT_USERAGENT, "freeswitch-curl/1.0"); http_data->sendfile_response = switch_core_alloc(http_data->pool, sizeof(char) * HTTP_SENDFILE_RESPONSE_SIZE); memset(http_data->sendfile_response, 0, sizeof(char) * HTTP_SENDFILE_RESPONSE_SIZE); // Set the function where we will copy out the response body data to curl_easy_setopt(http_data->curl_handle, CURLOPT_WRITEFUNCTION, http_sendfile_response_callback); curl_easy_setopt(http_data->curl_handle, CURLOPT_WRITEDATA, (void *) http_data); /* Add the file to upload as a POST form field */ curl_formadd(&http_data->formpost, &http_data->lastptr, CURLFORM_COPYNAME, http_data->filename_element_name, CURLFORM_FILE, http_data->filename_element, CURLFORM_END); if(!zstr(http_data->extrapost_elements)) { // Now to parse out the individual post element/value pairs char *argv[64] = { 0 }; // Probably don't need 64 but eh does it really use that much memory? uint32_t argc = 0; char *temp_extrapost = switch_core_strdup(http_data->pool, http_data->extrapost_elements); argc = switch_separate_string(temp_extrapost, '&', argv, (sizeof(argv) / sizeof(argv[0]))); for(count = 0; count < argc; count++) { char *argv2[4] = { 0 }; uint32_t argc2 = switch_separate_string(argv[count], '=', argv2, (sizeof(argv2) / sizeof(argv2[0]))); if(argc2 == 2) curl_formadd(&http_data->formpost, &http_data->lastptr, CURLFORM_COPYNAME, argv2[0], CURLFORM_COPYCONTENTS, argv2[1], CURLFORM_END); } } /* Fill in the submit field too, even if this isn't really needed */ curl_formadd(&http_data->formpost, &http_data->lastptr, CURLFORM_COPYNAME, "submit", CURLFORM_COPYCONTENTS, "or_die", CURLFORM_END); /* what URL that receives this POST */ curl_easy_setopt(http_data->curl_handle, CURLOPT_HTTPPOST, http_data->formpost); // This part actually fires off the curl, captures the HTTP response code, and then frees up the handle. curl_easy_perform(http_data->curl_handle); curl_easy_getinfo(http_data->curl_handle, CURLINFO_RESPONSE_CODE, &http_data->http_response_code); curl_easy_cleanup(http_data->curl_handle); // Clean up the form data from POST curl_formfree(http_data->formpost); }