switch_status_t perform_send_register_ack(listener_t *listener, const char *file, const char *func, int line, uint32_t keep_alive, char *date_format, char *reserved, uint32_t secondary_keep_alive, char *reserved2) { skinny_message_t *message; skinny_create_message(message, REGISTER_ACK_MESSAGE, reg_ack); message->data.reg_ack.keep_alive = keep_alive; memcpy(message->data.reg_ack.date_format, date_format, 6); switch_copy_string(message->data.reg_ack.reserved, reserved, 2); message->data.reg_ack.secondary_keep_alive = keep_alive; switch_copy_string(message->data.reg_ack.reserved2, reserved2, 4); if ( listener->profile->debug >= 9 ) { skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG, "Sending Register Ack with Keep Alive (%d), Date Format (%s), Secondary Keep Alive (%d)\n", keep_alive, date_format, secondary_keep_alive); } return skinny_send_reply_quiet(listener, message, SWITCH_TRUE); }
switch_status_t perform_send_forward_stat(listener_t *listener, const char *file, const char *func, int line, const char *number) { skinny_message_t *message; skinny_create_message(message, FORWARD_STAT_MESSAGE, forward_stat); if ( number && number[0] ) { message->data.forward_stat.active_forward = 1; message->data.forward_stat.line_instance = 1; message->data.forward_stat.forward_all_active = 1; message->data.forward_stat.forward_busy_active = 1; message->data.forward_stat.forward_noanswer_active = 1; switch_copy_string(message->data.forward_stat.forward_all_number, number, sizeof(message->data.forward_stat.forward_all_number)); switch_copy_string(message->data.forward_stat.forward_busy_number, number, sizeof(message->data.forward_stat.forward_all_number)); switch_copy_string(message->data.forward_stat.forward_noanswer_number, number, sizeof(message->data.forward_stat.forward_all_number)); skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG, "Sending ForwardStat with Number (%s)\n", number); } else { skinny_log_l_ffl_msg(listener, file, func, line, SWITCH_LOG_DEBUG, "Sending ForwardStat with No Number (Inactive)\n"); } return skinny_send_reply_quiet(listener, message, SWITCH_TRUE); }
static switch_status_t listen_entry(switch_core_session_t *session, dir_profile_t *profile, listing_callback_t *cbt) { char buf[2] = ""; char macro[256] = ""; char recorded_name[256] = ""; /* Try to use the recorded name from voicemail if it exist */ if (switch_loadable_module_exists("mod_voicemail") == SWITCH_STATUS_SUCCESS) { char *cmd = NULL; switch_stream_handle_t stream = { 0 }; SWITCH_STANDARD_STREAM(stream); cmd = switch_core_session_sprintf(session, "%s/%s@%s|name_path", cbt->params->profile, cbt->extension, cbt->params->domain); switch_api_execute("vm_prefs", cmd, session, &stream); if (strncmp("-ERR", stream.data, 4)) { switch_copy_string(recorded_name, (char *) stream.data, sizeof(recorded_name)); } switch_safe_free(stream.data); } if (zstr_buf(buf)) { switch_snprintf(macro, sizeof(macro), "phrase:%s:%d", DIR_RESULT_ITEM, cbt->want + 1); switch_ivr_read(session, 0, 1, macro, NULL, buf, sizeof(buf), 1, profile->terminator_key, 0); } if (!zstr_buf(recorded_name) && zstr_buf(buf)) { switch_ivr_read(session, 0, 1, recorded_name, NULL, buf, sizeof(buf), 1, profile->terminator_key, 0); } if (zstr_buf(recorded_name) && zstr_buf(buf)) { switch_snprintf(macro, sizeof(macro), "phrase:%s:%s", DIR_RESULT_SAY_NAME, cbt->fullname); switch_ivr_read(session, 0, 1, macro, NULL, buf, sizeof(buf), 1, profile->terminator_key, 0); } if (cbt->exten_visible && zstr_buf(buf)) { switch_snprintf(macro, sizeof(macro), "phrase:%s:%s", DIR_RESULT_AT, cbt->extension); switch_ivr_read(session, 0, 1, macro, NULL, buf, sizeof(buf), 1, profile->terminator_key, 0); } if (zstr_buf(buf)) { switch_snprintf(macro, sizeof(macro), "phrase:%s:%c,%c,%c,%c", DIR_RESULT_MENU, *profile->select_name_key, *profile->next_key, *profile->prev_key, *profile->new_search_key); switch_ivr_read(session, 0, 1, macro, NULL, buf, sizeof(buf), profile->digit_timeout, profile->terminator_key, 0); } if (!zstr_buf(buf)) { if (buf[0] == *profile->select_name_key) { switch_copy_string(cbt->transfer_to, cbt->extension, 255); } if (buf[0] == *profile->new_search_key) { cbt->new_search = 1; } if (buf[0] == *profile->prev_key) { cbt->move = ENTRY_MOVE_PREV; } } else { return SWITCH_STATUS_TIMEOUT; } return SWITCH_STATUS_SUCCESS; }
int skinny_speed_dial_get_callback(void *pArg, int argc, char **argv, char **columnNames) { struct speed_dial_get_helper *helper = pArg; helper->pos++; if (helper->pos == atoi(argv[0])) { /* wanted_position */ helper->button->number = helper->pos; /* value */ switch_copy_string(helper->button->line, argv[3], 24); /* value */ switch_copy_string(helper->button->label, argv[2], 40); /* label */ } return 0; }
int skinny_service_url_get_callback(void *pArg, int argc, char **argv, char **columnNames) { struct service_url_get_helper *helper = pArg; helper->pos++; if (helper->pos == atoi(argv[0])) { /* wanted_position */ helper->button->index = helper->pos; switch_copy_string(helper->button->url, argv[3], 256); /* value */ switch_copy_string(helper->button->display_name, argv[2], 40); /* label */ } return 0; }
int skinny_line_get_callback(void *pArg, int argc, char **argv, char **columnNames) { struct line_get_helper *helper = pArg; helper->pos++; if (helper->pos == atoi(argv[0])) { /* wanted_position */ helper->button->number = helper->pos; switch_copy_string(helper->button->name, argv[2], 24); /* label */ switch_copy_string(helper->button->shortname, argv[3], 40); /* value */ switch_copy_string(helper->button->displayname, argv[4], 44); /* caller_name */ } return 0; }
static int listing_callback(void *pArg, int argc, char **argv, char **columnNames) { listing_callback_t *cbt = (listing_callback_t *) pArg; if (cbt->index++ != cbt->want) { return 0; } switch_copy_string(cbt->extension, argv[0], 255); switch_copy_string(cbt->fullname, argv[1], 255); switch_copy_string(cbt->last_name, argv[2], 255); switch_copy_string(cbt->first_name, argv[3], 255); cbt->name_visible = atoi(argv[4]); cbt->exten_visible = atoi(argv[5]); return -1; }
switch_status_t perform_send_data(listener_t *listener, const char *file, const char *func, int line, uint32_t message_type, uint32_t application_id, uint32_t line_instance, uint32_t call_id, uint32_t transaction_id, uint32_t data_length, const char *data) { skinny_message_t *message; switch_assert(data_length == strlen(data)); /* data_length should be a multiple of 4 */ if ((data_length % 4) != 0) { data_length = (data_length / 4 + 1) * 4; } /* This one needs explicit allocation */ message = calloc(12+sizeof(message->data.data)+data_length-1, 1); message->type = message_type; message->length = 4 + sizeof(message->data.data)+data_length-1; message->data.data.application_id = application_id; message->data.data.line_instance = line_instance; message->data.data.call_id = call_id; message->data.data.transaction_id = transaction_id; message->data.data.data_length = data_length; switch_copy_string(message->data.data.data, data, data_length); skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG, "Send Data with Data Length (%d)\n", data_length); return skinny_send_reply_quiet(listener, message, SWITCH_TRUE); }
switch_status_t perform_send_display_pri_notify(listener_t *listener, const char *file, const char *func, int line, uint32_t message_timeout, uint32_t priority, char *notify) { skinny_message_t *message; char *tmp; skinny_create_message(message, DISPLAY_PRI_NOTIFY_MESSAGE, display_pri_notify); message->data.display_pri_notify.message_timeout = message_timeout; message->data.display_pri_notify.priority = priority; switch_copy_string(message->data.display_pri_notify.notify, notify, 32); tmp = skinny_format_message(notify); skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG, "Send Display Pri Notify with Timeout (%d), Priority (%d), Message (%s)\n", message_timeout, priority, tmp); switch_safe_free(tmp); return skinny_send_reply_quiet(listener, message, SWITCH_TRUE); }
SWITCH_DECLARE(const char *) switch_dir_next_file(switch_dir_t *thedir, char *buf, switch_size_t len) { const char *fname = NULL; apr_int32_t finfo_flags = APR_FINFO_DIRENT | APR_FINFO_TYPE | APR_FINFO_NAME; const char *name; while (apr_dir_read(&(thedir->finfo), finfo_flags, thedir->dir_handle) == SWITCH_STATUS_SUCCESS) { if (thedir->finfo.filetype != APR_REG) { continue; } if (!(name = thedir->finfo.fname)) { name = thedir->finfo.name; } if (!name) { continue; } if (name) { switch_copy_string(buf, name, len); fname = buf; break; } else { continue; } } return fname; }
switch_status_t perform_send_display_prompt_status_textid(listener_t *listener, const char *file, const char *func, int line, uint32_t timeout, uint32_t display_textid, uint32_t line_instance, uint32_t call_id) { skinny_message_t *message; char *label; skinny_create_message(message, DISPLAY_PROMPT_STATUS_MESSAGE, display_prompt_status); message->data.display_prompt_status.timeout = timeout; label = skinny_textid2raw(display_textid); switch_copy_string(message->data.display_prompt_status.display, label, 32); switch_safe_free(label); message->data.display_prompt_status.line_instance = line_instance; message->data.display_prompt_status.call_id = call_id; skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG, "Send Display Prompt Status with Timeout (%d), Display (%s), Line Instance (%d), Call ID (%d)\n", timeout, skinny_textid2str(display_textid), line_instance, call_id); return skinny_send_reply_quiet(listener, message, SWITCH_TRUE); }
static int sql2str_callback(void *pArg, int argc, char **argv, char **columnNames) { callback_t *cbt = (callback_t *) pArg; switch_copy_string(cbt->buf, argv[0], cbt->len); cbt->matches++; return 0; }
static int get_pmp_pubaddr(char *pub_addr) { int r = 0, i = 0, max = 5; natpmpresp_t response; char *pubaddr = NULL; fd_set fds; natpmp_t natpmp; const char *err = NULL; if ((r = initnatpmp(&natpmp)) < 0) { err = "init failed"; goto end; } if ((r = sendpublicaddressrequest(&natpmp)) < 0) { err = "pub addr req failed"; goto end; } do { struct timeval timeout = { 1, 0 }; i++; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Checking for PMP %d/%d\n", i, max); FD_ZERO(&fds); FD_SET(natpmp.s, &fds); if ((r = getnatpmprequesttimeout(&natpmp, &timeout)) < 0) { err = "get timeout failed"; goto end; } if ((r = select(FD_SETSIZE, &fds, NULL, NULL, &timeout)) < 0) { err = "select failed"; goto end; } r = readnatpmpresponseorretry(&natpmp, &response); } while (r == NATPMP_TRYAGAIN && i < max); if (r < 0) { err = "general error"; goto end; } pubaddr = inet_ntoa(response.pnu.publicaddress.addr); switch_copy_string(pub_addr, pubaddr, IP_LEN); nat_globals.nat_type = SWITCH_NAT_TYPE_PMP; closenatpmp(&natpmp); end: if (err) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error checking for PMP [%s]\n", err); } return r; }
static xmlrpc_value *freeswitch_man(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, void *const userData) { char *oid = NULL, *relative_oid, *s_action = NULL, *data = NULL; char buf[SWITCH_MAX_MANAGEMENT_BUFFER_LEN] = ""; switch_management_action_t action = SMA_NONE; xmlrpc_value *val = NULL; /* Parse our argument array. */ xmlrpc_decompose_value(envP, paramArrayP, "(sss)", &oid, &s_action, &data); if (envP->fault_occurred) { return NULL; } if (!strncasecmp(oid, FREESWITCH_OID_PREFIX, strlen(FREESWITCH_OID_PREFIX))) { relative_oid = oid + strlen(FREESWITCH_OID_PREFIX); } else { relative_oid = oid; } if (!zstr(data)) { switch_copy_string(buf, data, sizeof(buf)); } if (!strcasecmp(s_action, "get")) { action = SMA_GET; } else if (!strcasecmp(s_action, "set")) { action = SMA_SET; } if (action) { if (switch_core_management_exec(relative_oid, action, buf, sizeof(buf)) == SWITCH_STATUS_SUCCESS) { if (action == SMA_SET) { if (*buf != '\0') { switch_snprintf(buf, sizeof(buf), "OK\n"); } } } else { if (*buf != '\0') { switch_snprintf(buf, sizeof(buf), "ERROR\n"); } } } else { switch_snprintf(buf, sizeof(buf), "Invalid Action %s\n", s_action); } /* Return our result. */ val = xmlrpc_build_value(envP, "s", buf); /* xmlrpc-c requires us to free memory it malloced from xmlrpc_decompose_value */ switch_safe_free(oid); switch_safe_free(s_action); switch_safe_free(data); return val; }
static void cepstral_text_param_tts(switch_speech_handle_t *sh, char *param, const char *val) { cepstral_t *cepstral; cepstral = sh->private_info; assert(cepstral != NULL); if (!strcasecmp(param, "voice")) { const char *voice_name = val; if (!strcasecmp(voice_name, "next")) { if ((cepstral->voice = swift_port_find_next_voice(cepstral->port))) { if (SWIFT_FAILED(swift_port_set_voice(cepstral->port, cepstral->voice))) { cepstral->done = cepstral->done_gen = 1; return; } voice_name = swift_voice_get_attribute(cepstral->voice, "name"); } else { voice_name = NULL; } } else { if (voice_name && SWIFT_FAILED(swift_port_set_voice_by_name(cepstral->port, voice_name))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid voice %s!\n", voice_name); voice_name = NULL; } } if (!voice_name) { /* Find the first voice on the system */ if ((cepstral->voice = swift_port_find_first_voice(cepstral->port, NULL, NULL)) == NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to find any voices!\n"); cepstral->done = cepstral->done_gen = 1; return; } /* Set the voice found by find_first_voice() as the port's current voice */ if (SWIFT_FAILED(swift_port_set_voice(cepstral->port, cepstral->voice))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set voice.\n"); cepstral->done = cepstral->done_gen = 1; return; } voice_name = swift_voice_get_attribute(cepstral->voice, "name"); } if (voice_name) { switch_copy_string(sh->voice, voice_name, sizeof(sh->voice)); } return; } swift_port_set_param_string(cepstral->port, param, val, NULL); }
int skinny_feature_get_callback(void *pArg, int argc, char **argv, char **columnNames) { struct feature_get_helper *helper = pArg; helper->pos++; if (helper->pos == atoi(argv[0])) { /* wanted_position */ helper->button->index = helper->pos; helper->button->id = helper->pos; switch_copy_string(helper->button->text_label, argv[2], 40); /* label */ helper->button->status = atoi(argv[3]); /* value */ } return 0; }
switch_status_t perform_send_speed_dial_stat_res(listener_t *listener, const char *file, const char *func, int line, uint32_t number, char *speed_line, char *speed_label) { skinny_message_t *message; skinny_create_message(message, SPEED_DIAL_STAT_RES_MESSAGE, speed_dial_res); message->data.speed_dial_res.number = number; switch_copy_string(message->data.speed_dial_res.line, speed_line, 24); switch_copy_string(message->data.speed_dial_res.label, speed_label, 40); if ( listener->profile->debug >= 9 ) { skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG, "Sending Speed Dial Stat Res with Number (%d), Line (%s), Label (%s)\n", number, speed_line, speed_label); } return skinny_send_reply_quiet(listener, message, SWITCH_TRUE); }
static size_t header_callback(void *ptr, size_t size, size_t nmemb, void *data) { register unsigned int realsize = (unsigned int) (size * nmemb); http_data_t *http_data = data; char *header = NULL; header = switch_core_alloc(http_data->pool, realsize + 1); switch_copy_string(header, ptr, realsize); header[realsize] = '\0'; http_data->headers = switch_curl_slist_append(http_data->headers, header); return realsize; }
switch_status_t gather_name_digit(switch_core_session_t *session, dir_profile_t *profile, search_params_t *params) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_status_t status = SWITCH_STATUS_SUCCESS; cbr_t cbr; int loop = 1; switch_input_args_t args = { 0 }; args.input_callback = on_dtmf; args.buf = &cbr; while (switch_channel_ready(channel) && loop) { char macro[255]; loop = 0; memset(&cbr, 0, sizeof(cbr)); cbr.profile = profile; params->timeout = 0; /* Gather the user Name */ switch_snprintf(macro, sizeof(macro), "%s:%c", (params->search_by == SEARCH_BY_LAST_NAME ? "last_name" : "first_name"), *profile->switch_order_key); switch_ivr_phrase_macro(session, DIR_INTRO, macro, NULL, &args); while (switch_channel_ready(channel)) { if (cbr.digit == *profile->terminator_key) { status = SWITCH_STATUS_BREAK; break; } if (cbr.digit == *profile->switch_order_key) { if (params->search_by == SEARCH_BY_LAST_NAME) { params->search_by = SEARCH_BY_FIRST_NAME; } else { params->search_by = SEARCH_BY_LAST_NAME; } loop = 1; break; } if (switch_ivr_collect_digits_callback(session, &args, profile->digit_timeout, 0) == SWITCH_STATUS_TIMEOUT) { params->timeout = 1; break; } } } switch_copy_string(params->digits, cbr.digits, 255); return status; }
switch_status_t perform_send_register_reject(listener_t *listener, const char *file, const char *func, int line, char *error) { skinny_message_t *message; skinny_create_message(message, REGISTER_REJECT_MESSAGE, reg_rej); switch_copy_string(message->data.reg_rej.error, error, 33); skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG, "Send Register Reject with Error (%s)\n", error); return skinny_send_reply_quiet(listener, message, SWITCH_TRUE); }
switch_status_t perform_send_extended_data(listener_t *listener, const char *file, const char *func, int line, uint32_t message_type, uint32_t application_id, uint32_t line_instance, uint32_t call_id, uint32_t transaction_id, uint32_t data_length, uint32_t sequence_flag, uint32_t display_priority, uint32_t conference_id, uint32_t app_instance_id, uint32_t routing_id, const char *data) { skinny_message_t *message; switch_assert(data_length == strlen(data)); /* data_length should be a multiple of 4 */ if ((data_length % 4) != 0) { data_length = (data_length / 4 + 1) * 4; } /* This one needs explicit allocation */ message = calloc(12+sizeof(message->data.extended_data)+data_length-1, 1); message->type = message_type; message->length = 4 + sizeof(message->data.extended_data)+data_length-1; message->data.extended_data.application_id = application_id; message->data.extended_data.line_instance = line_instance; message->data.extended_data.call_id = call_id; message->data.extended_data.transaction_id = transaction_id; message->data.extended_data.data_length = data_length; message->data.extended_data.sequence_flag = sequence_flag; message->data.extended_data.display_priority = display_priority; message->data.extended_data.conference_id = conference_id; message->data.extended_data.app_instance_id = app_instance_id; message->data.extended_data.routing_id = routing_id; switch_copy_string(message->data.extended_data.data, data, data_length); skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG, "Send Extended Data with Application ID (%d), Line Instance (%d), Call ID (%d), ...\n", application_id, line_instance, call_id ); return skinny_send_reply_quiet(listener, message, SWITCH_TRUE); }
switch_status_t perform_send_srvreq_response(listener_t *listener, const char *file, const char *func, int line, char *ip, uint32_t port) { skinny_message_t *message; skinny_create_message(message, SERVER_RESPONSE_MESSAGE, serv_res_mess); message->data.serv_res_mess.serverListenPort[0] = port; switch_inet_pton(AF_INET,ip, &message->data.serv_res_mess.serverIpAddr[0]); switch_copy_string(message->data.serv_res_mess.server[0].serverName,ip,sizeof(message->data.serv_res_mess.server[0].serverName)); skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG, "Sending Server Request Response with IP (%s) and Port (%d)\n", ip, port); return skinny_send_reply(listener, message, SWITCH_TRUE); }
static int route_callback(void *pArg, int argc, char **argv, char **columnNames) { route_callback_t *cbt = (route_callback_t *) pArg; switch_copy_string(cbt->gateway, argv[0], 128); switch_copy_string(cbt->group, argv[1], 128); switch_copy_string(cbt->limit, argv[2], 128); switch_copy_string(cbt->techprofile, argv[3], 128); switch_copy_string(cbt->acctcode, argv[4], 128); switch_copy_string(cbt->translated, argv[5], 16); return 0; }
static size_t http_sendfile_response_callback(void *ptr, size_t size, size_t nmemb, void *data) { register unsigned int realsize = (unsigned int) (size * nmemb); http_sendfile_data_t *http_data = data; if(http_data->sendfile_response_count + realsize < HTTP_SENDFILE_RESPONSE_SIZE) { // I'm not sure why we need the (realsize+1) here, but it truncates the data by 1 char if I don't do this switch_copy_string(&http_data->sendfile_response[http_data->sendfile_response_count], ptr, (realsize+1)); http_data->sendfile_response_count += realsize; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Response page is more than %d bytes long, truncating.\n", HTTP_SENDFILE_RESPONSE_SIZE); realsize = 0; } return realsize; }
switch_status_t perform_send_dialed_number(listener_t *listener, const char *file, const char *func, int line, char called_party[24], uint32_t line_instance, uint32_t call_id) { skinny_message_t *message; skinny_create_message(message, DIALED_NUMBER_MESSAGE, dialed_number); switch_copy_string(message->data.dialed_number.called_party, called_party, 24); message->data.dialed_number.line_instance = line_instance; message->data.dialed_number.call_id = call_id; skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG, "Send Dialed Number with Number (%s), Line Instance (%d), Call ID (%d)\n", called_party, line_instance, call_id); return skinny_send_reply_quiet(listener, message, SWITCH_TRUE); }
static switch_bool_t fsk_detect_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) { switch_fsk_detect_t *pvt = (switch_fsk_detect_t *) user_data; //switch_frame_t *frame = NULL; switch_channel_t *channel = switch_core_session_get_channel(pvt->session); switch (type) { case SWITCH_ABC_TYPE_INIT: { switch_codec_implementation_t read_impl = { 0 }; switch_core_session_get_read_impl(pvt->session, &read_impl); if (fsk_demod_init(&pvt->fsk_data, read_impl.actual_samples_per_second, pvt->fbuf, sizeof(pvt->fbuf))) { return SWITCH_FALSE; } break; } case SWITCH_ABC_TYPE_CLOSE: { fsk_demod_destroy(&pvt->fsk_data); } break; case SWITCH_ABC_TYPE_WRITE_REPLACE: case SWITCH_ABC_TYPE_READ_REPLACE: { switch_frame_t *rframe; if (type == SWITCH_ABC_TYPE_READ_REPLACE) { rframe = switch_core_media_bug_get_read_replace_frame(bug); } else { rframe = switch_core_media_bug_get_write_replace_frame(bug); } if (!pvt->skip && fsk_demod_feed(&pvt->fsk_data, rframe->data, rframe->datalen / 2) != SWITCH_STATUS_SUCCESS) { char str[1024] = ""; size_t type, mlen; char *sp; switch_event_t *event; const char *app_var; int total = 0; switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA); while(fsk_data_parse(&pvt->fsk_data, &type, &sp, &mlen) == SWITCH_STATUS_SUCCESS) { char *varname = NULL, *val, *p; switch_copy_string(str, sp, mlen+1); *(str+mlen) = '\0'; switch_clean_string(str); //printf("TYPE %u LEN %u VAL [%s]\n", (unsigned)type, (unsigned)mlen, str); val = str; switch(type) { case MDMF_DATETIME: varname = "fsk_datetime"; break; case MDMF_PHONE_NAME: varname = "fsk_phone_name"; break; case MDMF_PHONE_NUM: varname = "fsk_phone_num"; break; case MDMF_NAME_VALUE: varname = switch_core_session_sprintf(pvt->session, "fsk_%s", val); if ((p = strchr(varname, ':'))) { *p++ = '\0'; val = p; } break; default: break; } if (varname && val) { total++; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s setting FSK var [%s][%s]\n", switch_channel_get_name(channel), varname, val); switch_channel_set_variable(channel, varname, val); if (event) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, varname, val); } } } if (event) { if (switch_core_session_queue_event(pvt->session, &event) != SWITCH_STATUS_SUCCESS) { switch_event_destroy(&event); } } if (total && (app_var = switch_channel_get_variable(channel, "execute_on_fsk"))) { char *app_arg; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s processing execute_on_fsk [%s]\n", switch_channel_get_name(channel), app_var); if ((app_arg = strchr(app_var, ' '))) { *app_arg++ = '\0'; } switch_core_session_execute_application(pvt->session, app_var, app_arg); } pvt->skip = 10; } memset(rframe->data, 255, rframe->datalen); if (type == SWITCH_ABC_TYPE_READ_REPLACE) { switch_core_media_bug_set_read_replace_frame(bug, rframe); } else { switch_core_media_bug_set_write_replace_frame(bug, rframe); } if (pvt->skip && !--pvt->skip) { return SWITCH_FALSE; } } break; case SWITCH_ABC_TYPE_WRITE: default: break; } return SWITCH_TRUE; }
/* 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; }
switch_status_t navigate_entrys(switch_core_session_t *session, dir_profile_t *profile, search_params_t *params) { switch_status_t status = SWITCH_STATUS_SUCCESS; char *sql = NULL, *sql_where = NULL; char entry_count[80] = ""; callback_t cbt = { 0 }; int result_count; char macro[256] = ""; listing_callback_t listing_cbt; int cur_entry = 0; cbt.buf = entry_count; cbt.len = sizeof(entry_count); if (params->search_by == SEARCH_BY_FIRST_AND_LAST_NAME) { sql_where = switch_mprintf("hostname = '%q' and uuid = '%q' and name_visible = 1 and (%s like '%q%%' or %s like '%q%%')", globals.hostname, switch_core_session_get_uuid(session), "last_name_digit", params->digits, "first_name_digit", params->digits); } else if (params->search_by == SEARCH_BY_FULL_NAME) { sql_where = switch_mprintf("hostname = '%q' and uuid = '%q' and name_visible = 1 and full_name_digit like '%%%q%%'", globals.hostname, switch_core_session_get_uuid(session), "last_name_digit", params->digits, "first_name_digit", params->digits); } else { sql_where = switch_mprintf("hostname = '%q' and uuid = '%q' and name_visible = 1 and %s like '%q%%'", globals.hostname, switch_core_session_get_uuid(session), (params->search_by == SEARCH_BY_LAST_NAME ? "last_name_digit" : "first_name_digit"), params->digits); } sql = switch_mprintf("select count(*) from directory_search where %s", sql_where); directory_execute_sql_callback(globals.mutex, sql, sql2str_callback, &cbt); switch_safe_free(sql); result_count = atoi(entry_count); if (result_count == 0) { switch_snprintf(macro, sizeof(macro), "%d", result_count); switch_ivr_phrase_macro(session, DIR_RESULT_COUNT, macro, NULL, NULL); params->try_again = 1; status = SWITCH_STATUS_BREAK; goto end; } else if (profile->max_result != 0 && result_count > profile->max_result) { switch_ivr_phrase_macro(session, DIR_RESULT_COUNT_TOO_LARGE, NULL, NULL, NULL); params->try_again = 1; status = SWITCH_STATUS_BREAK; goto end; } else { switch_snprintf(macro, sizeof(macro), "%d", result_count); switch_ivr_phrase_macro(session, DIR_RESULT_COUNT, macro, NULL, NULL); } memset(&listing_cbt, 0, sizeof(listing_cbt)); listing_cbt.params = params; sql = switch_mprintf("select extension, full_name, last_name, first_name, name_visible, exten_visible from directory_search where %s order by last_name, first_name", sql_where); for (cur_entry = 0; cur_entry < result_count; cur_entry++) { listing_cbt.index = 0; listing_cbt.want = cur_entry; listing_cbt.move = ENTRY_MOVE_NEXT; directory_execute_sql_callback(globals.mutex, sql, listing_callback, &listing_cbt); status = listen_entry(session, profile, &listing_cbt); if (!zstr(listing_cbt.transfer_to)) { switch_copy_string(params->transfer_to, listing_cbt.transfer_to, 255); break; } if (listing_cbt.new_search) { params->try_again = 1; goto end; } if (listing_cbt.move == ENTRY_MOVE_NEXT) { if (cur_entry == result_count - 1) { switch_snprintf(macro, sizeof(macro), "%d", result_count); switch_ivr_phrase_macro(session, DIR_RESULT_LAST, macro, NULL, NULL); cur_entry -= 1; } } if (listing_cbt.move == ENTRY_MOVE_PREV) { if (cur_entry <= 0) { cur_entry = -1; } else { cur_entry -= 2; } } if (status == SWITCH_STATUS_TIMEOUT) { goto end; } if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) { goto end; } } end: switch_safe_free(sql); switch_safe_free(sql_where); return status; }
static switch_status_t sndfile_file_open(switch_file_handle_t *handle, const char *path) { sndfile_context *context; int mode = 0; char *ext; struct format_map *map = NULL; switch_status_t status = SWITCH_STATUS_SUCCESS; char *alt_path = NULL, *last, *ldup = NULL; size_t alt_len = 0; int rates[4] = { 8000, 16000, 32000, 48000 }; int i; sf_count_t frames = 0; #ifdef WIN32 char ps = '/'; #else char ps = '/'; #endif if ((ext = strrchr(path, '.')) == 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Format\n"); return SWITCH_STATUS_GENERR; } ext++; if (switch_test_flag(handle, SWITCH_FILE_FLAG_READ)) { mode += SFM_READ; } if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) { if (switch_test_flag(handle, SWITCH_FILE_WRITE_APPEND) || switch_test_flag(handle, SWITCH_FILE_WRITE_OVER) || handle->offset_pos) { mode += SFM_RDWR; } else { mode += SFM_WRITE; } } if (!mode) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Mode!\n"); return SWITCH_STATUS_GENERR; } if ((context = switch_core_alloc(handle->memory_pool, sizeof(*context))) == 0) { return SWITCH_STATUS_MEMERR; } map = switch_core_hash_find(globals.format_hash, ext); if (mode & SFM_WRITE) { context->sfinfo.channels = handle->channels; context->sfinfo.samplerate = handle->samplerate; if (handle->samplerate == 8000 || handle->samplerate == 16000 || handle->samplerate == 24000 || handle->samplerate == 32000 || handle->samplerate == 48000 || handle->samplerate == 11025 || handle->samplerate == 22050 || handle->samplerate == 44100) { context->sfinfo.format |= SF_FORMAT_PCM_16; } } if (map) { context->sfinfo.format |= map->format; } if (!strcmp(ext, "r8") || !strcmp(ext, "raw")) { context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_16; context->sfinfo.channels = 1; context->sfinfo.samplerate = 8000; } else if (!strcmp(ext, "r16")) { context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_16; context->sfinfo.channels = 1; context->sfinfo.samplerate = 16000; } else if (!strcmp(ext, "r24")) { context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_24; context->sfinfo.channels = 1; context->sfinfo.samplerate = 24000; } else if (!strcmp(ext, "r32")) { context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_32; context->sfinfo.channels = 1; context->sfinfo.samplerate = 32000; } else if (!strcmp(ext, "gsm")) { context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_GSM610; context->sfinfo.channels = 1; context->sfinfo.samplerate = 8000; } else if (!strcmp(ext, "ul") || !strcmp(ext, "ulaw")) { context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_ULAW; context->sfinfo.channels = 1; context->sfinfo.samplerate = 8000; } else if (!strcmp(ext, "al") || !strcmp(ext, "alaw")) { context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_ALAW; context->sfinfo.channels = 1; context->sfinfo.samplerate = 8000; } else if (!strcmp(ext, "vox")) { context->sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM; context->sfinfo.channels = 1; context->sfinfo.samplerate = 8000; } else if (!strcmp(ext, "adpcm")) { context->sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM; context->sfinfo.channels = 1; context->sfinfo.samplerate = 8000; } else if (!strcmp(ext, "oga")) { context->sfinfo.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS; context->sfinfo.samplerate = handle->samplerate; } if ((mode & SFM_WRITE) && sf_format_check(&context->sfinfo) == 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error : file format is invalid (0x%08X).\n", context->sfinfo.format); return SWITCH_STATUS_GENERR; } alt_len = strlen(path) + 10; switch_zmalloc(alt_path, alt_len); switch_copy_string(alt_path, path, alt_len); /* This block attempts to add the sample rate to the path if the sample rate is already present in the path it does nothing and reverts to the original file name. */ if ((last = strrchr(alt_path, ps))) { last++; #ifdef WIN32 if (strrchr(last, '\\')) { last = strrchr(alt_path, '\\'); /* do not swallow a back slash if they are intermixed under windows */ last++; } #endif ldup = strdup(last); switch_assert(ldup); switch_snprintf(last, alt_len - (last - alt_path), "%d%s%s", handle->samplerate, SWITCH_PATH_SEPARATOR, ldup); if ((context->handle = sf_open(alt_path, mode, &context->sfinfo))) { path = alt_path; } else { /* Try to find the file at the highest rate possible if we can't find one that matches the exact rate. If we don't find any, we will default back to the original file name. */ for (i = 3; i >= 0; i--) { switch_snprintf(last, alt_len - (last - alt_path), "%d%s%s", rates[i], SWITCH_PATH_SEPARATOR, ldup); if ((context->handle = sf_open(alt_path, mode, &context->sfinfo))) { path = alt_path; break; } } } } if (!context->handle) { if ((context->handle = sf_open(path, mode, &context->sfinfo)) == 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening File [%s] [%s]\n", path, sf_strerror(context->handle)); status = SWITCH_STATUS_GENERR; goto end; } } //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opening File [%s] rate %dhz\n", path, context->sfinfo.samplerate); handle->samples = (unsigned int) context->sfinfo.frames; handle->samplerate = context->sfinfo.samplerate; handle->channels = (uint8_t) context->sfinfo.channels; handle->format = context->sfinfo.format; handle->sections = context->sfinfo.sections; handle->seekable = context->sfinfo.seekable; handle->speed = 0; handle->private_info = context; if (handle->offset_pos) { frames = handle->offset_pos; handle->offset_pos = 0; } if (switch_test_flag(handle, SWITCH_FILE_WRITE_APPEND)) { handle->pos = sf_seek(context->handle, frames, SEEK_END); } else if (switch_test_flag(handle, SWITCH_FILE_WRITE_OVER)) { handle->pos = sf_seek(context->handle, frames, SEEK_SET); } else { sf_command(context->handle, SFC_FILE_TRUNCATE, &frames, sizeof(frames)); } end: switch_safe_free(alt_path); switch_safe_free(ldup); return status; }