static switch_status_t spy_on_hangup(switch_core_session_t *session) { switch_channel_t *channel = switch_core_session_get_channel(session); const char *data = switch_channel_get_private(channel, "_userspy_"); const char *uuid = switch_core_session_get_uuid(session); spy_t *spy = NULL, *p = NULL, *prev = NULL; switch_thread_rwlock_wrlock(globals.spy_hash_lock); spy = switch_core_hash_find(globals.spy_hash, data); for (p = spy; p; p = p->next) { if (p->uuid == uuid) { if (prev) { prev->next = p->next; } else { spy = p->next; } globals.spy_count--; break; } prev = p; } switch_core_hash_insert(globals.spy_hash, data, spy); switch_thread_rwlock_unlock(globals.spy_hash_lock); return SWITCH_STATUS_SUCCESS; }
SWITCH_DECLARE_CONSTRUCTOR CoreSession::CoreSession(char *nuuid, CoreSession *a_leg) { switch_channel_t *other_channel = NULL; init_vars(); if (a_leg && a_leg->session) { other_channel = switch_core_session_get_channel(a_leg->session); } if (!strchr(nuuid, '/') && (session = switch_core_session_force_locate(nuuid))) { uuid = strdup(nuuid); channel = switch_core_session_get_channel(session); allocated = 1; } else { cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; if (switch_ivr_originate(a_leg ? a_leg->session : NULL, &session, &cause, nuuid, 60, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL) == SWITCH_STATUS_SUCCESS) { channel = switch_core_session_get_channel(session); allocated = 1; switch_set_flag(this, S_HUP); uuid = strdup(switch_core_session_get_uuid(session)); switch_channel_set_state(switch_core_session_get_channel(session), CS_SOFT_EXECUTE); switch_channel_wait_for_state(channel, other_channel, CS_SOFT_EXECUTE); } } }
WSChannel* WSClientParser::CreateChannel(switch_core_session_t *session) { WSChannel *wsChannel = NULL; // 创建channel // switch_memory_pool_t *pool = switch_core_session_get_pool(session); wsChannel = (WSChannel *)switch_core_alloc(mpPool, sizeof(WSChannel)); wsChannel->session = session; wsChannel->parser = this; wsChannel->uuid_str = switch_core_strdup(mpPool, switch_core_session_get_uuid(session)); switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->GetUUID()), SWITCH_LOG_INFO, "WSClientParser::CreateChannel( " "this : %p, " "wsChannel : %p " ") \n", this, wsChannel ); if( InitChannel(wsChannel) ) { mpChannel = wsChannel; } else { DestroyChannel(wsChannel); } return wsChannel; }
void conference_event_adv_la(conference_obj_t *conference, conference_member_t *member, switch_bool_t join) { //if (switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY) { switch_channel_set_flag(member->channel, CF_VIDEO_REFRESH_REQ); switch_core_media_gen_key_frame(member->session); //} if (conference && conference->la && member->session && !switch_channel_test_flag(member->channel, CF_VIDEO_ONLY)) { cJSON *msg, *data; const char *uuid = switch_core_session_get_uuid(member->session); const char *cookie = switch_channel_get_variable(member->channel, "event_channel_cookie"); const char *event_channel = cookie ? cookie : uuid; switch_event_t *variables; switch_event_header_t *hp; msg = cJSON_CreateObject(); data = json_add_child_obj(msg, "pvtData", NULL); cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(event_channel)); cJSON_AddItemToObject(msg, "eventType", cJSON_CreateString("channelPvtData")); cJSON_AddItemToObject(data, "action", cJSON_CreateString(join ? "conference-liveArray-join" : "conference-liveArray-part")); cJSON_AddItemToObject(data, "laChannel", cJSON_CreateString(conference->la_event_channel)); cJSON_AddItemToObject(data, "laName", cJSON_CreateString(conference->la_name)); cJSON_AddItemToObject(data, "role", cJSON_CreateString(conference_utils_member_test_flag(member, MFLAG_MOD) ? "moderator" : "participant")); cJSON_AddItemToObject(data, "chatID", cJSON_CreateString(conference->chat_id)); cJSON_AddItemToObject(data, "canvasCount", cJSON_CreateNumber(conference->canvas_count)); if (conference_utils_member_test_flag(member, MFLAG_SECOND_SCREEN)) { cJSON_AddItemToObject(data, "secondScreen", cJSON_CreateTrue()); } if (conference_utils_member_test_flag(member, MFLAG_MOD)) { cJSON_AddItemToObject(data, "modChannel", cJSON_CreateString(conference->mod_event_channel)); } cJSON_AddItemToObject(data, "chatChannel", cJSON_CreateString(conference->chat_event_channel)); switch_core_get_variables(&variables); for (hp = variables->headers; hp; hp = hp->next) { if (!strncasecmp(hp->name, "conference_verto_", 17)) { char *var = hp->name + 17; if (var) { cJSON_AddItemToObject(data, var, cJSON_CreateString(hp->value)); } } } switch_event_destroy(&variables); switch_event_channel_broadcast(event_channel, &msg, "mod_conference", conference_globals.event_channel_id); if (cookie) { switch_event_channel_permission_modify(cookie, conference->la_event_channel, join); switch_event_channel_permission_modify(cookie, conference->mod_event_channel, join); switch_event_channel_permission_modify(cookie, conference->chat_event_channel, join); } } }
/** * Start execution of call output component * @param component to start * @param session the session to output to * @param output the output request * @param iq the original request */ static iks *start_call_output(struct rayo_component *component, switch_core_session_t *session, iks *output, iks *iq) { switch_stream_handle_t stream = { 0 }; /* acknowledge command */ rayo_component_send_start(component, iq); /* build playback command */ SWITCH_STANDARD_STREAM(stream); stream.write_function(&stream, "{id=%s,session=%s,pause=%s", RAYO_JID(component), switch_core_session_get_uuid(session), OUTPUT_COMPONENT(component)->start_paused ? "true" : "false"); if (OUTPUT_COMPONENT(component)->max_time > 0) { stream.write_function(&stream, ",timeout=%i", OUTPUT_COMPONENT(component)->max_time * 1000); } stream.write_function(&stream, "}fileman://rayo://%s", RAYO_JID(component)); if (switch_ivr_displace_session(session, stream.data, 0, "m") == SWITCH_STATUS_SUCCESS) { RAYO_UNLOCK(component); } else { if (OUTPUT_COMPONENT(component)->document) { iks_delete(OUTPUT_COMPONENT(component)->document); } if (switch_channel_get_state(switch_core_session_get_channel(session)) >= CS_HANGUP) { rayo_component_send_complete(component, COMPONENT_COMPLETE_HANGUP); component = NULL; } else { rayo_component_send_complete(component, COMPONENT_COMPLETE_ERROR); component = NULL; } } switch_safe_free(stream.data); return NULL; }
static valet_token_t *next_id(switch_core_session_t *session, valet_lot_t *lot, int min, int max, int in) { int i, r = 0; char buf[256] = ""; valet_token_t *token; if (!min) { min = 1; } switch_mutex_lock(globals.mutex); if (!in) { int longest = find_longest(lot, min, max); if (longest > 0) { switch_snprintf(buf, sizeof(buf), "%d", longest); switch_mutex_lock(lot->mutex); token = (valet_token_t *) switch_core_hash_find(lot->hash, buf); switch_mutex_unlock(lot->mutex); if (token) { goto end; } } } for (i = min; (i < max || max == 0); i++) { switch_snprintf(buf, sizeof(buf), "%d", i); switch_mutex_lock(lot->mutex); token = (valet_token_t *) switch_core_hash_find(lot->hash, buf); switch_mutex_unlock(lot->mutex); if ((!in && token && !token->timeout)) { goto end; } if (in && !token) { r = i; break; } } token = NULL; if (r) { switch_snprintf(buf, sizeof(buf), "%d", r); switch_zmalloc(token, sizeof(*token)); switch_set_string(token->uuid, switch_core_session_get_uuid(session)); switch_set_string(token->ext, buf); token->start_time = switch_epoch_time_now(NULL); switch_mutex_lock(lot->mutex); switch_core_hash_insert(lot->hash, buf, token); switch_mutex_unlock(lot->mutex); } end: switch_mutex_unlock(globals.mutex); return token; }
static void tech_attach(private_t *tech_pvt, modem_t *modem) { tech_pvt->modem = modem; switch_set_string(modem->uuid_str, switch_core_session_get_uuid(tech_pvt->session)); switch_channel_set_variable_printf(tech_pvt->channel, "modem_slot", "%d", modem->slot); switch_channel_set_variable(tech_pvt->channel, "modem_devlink", modem->devlink); switch_channel_set_variable(tech_pvt->channel, "modem_digits", modem->digits); switch_channel_export_variable(tech_pvt->channel, "rtp_autoflush_during_bridge", "false", SWITCH_EXPORT_VARS_VARIABLE); }
/** * Process a buffer of audio data for call progress tones * * @param bug the session's media bug * @param user_data the detector * @param type the type of data available from the bug * @return SWITCH_TRUE */ static switch_bool_t callprogress_detector_process_buffer(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) { uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE]; switch_frame_t frame = { 0 }; tone_detector_t *detector = (tone_detector_t *)user_data; switch_core_session_t *session = switch_core_media_bug_get_session(bug); switch_channel_t *channel = switch_core_session_get_channel(session); frame.data = data; frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE; switch(type) { case SWITCH_ABC_TYPE_INIT: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "(%s) initializing tone detector\n", switch_channel_get_name(channel)); tone_detector_init(detector); break; case SWITCH_ABC_TYPE_READ: { const char *detected_tone = NULL; if (!detector->spandsp_detector) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "(%s) detector is destroyed\n", switch_channel_get_name(channel)); return SWITCH_FALSE; } if (switch_core_media_bug_read(bug, &frame, SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "(%s) error reading frame\n", switch_channel_get_name(channel)); return SWITCH_FALSE; } tone_detector_process_buffer(detector, frame.data, frame.samples, &detected_tone); if (detected_tone) { switch_event_t *event = NULL; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "(%s) DETECTED TONE: %s\n", switch_channel_get_name(channel), detected_tone); if (switch_event_create(&event, SWITCH_EVENT_DETECTED_TONE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detected-Tone", detected_tone); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(session)); switch_event_fire(&event); } } break; } case SWITCH_ABC_TYPE_WRITE: break; case SWITCH_ABC_TYPE_WRITE_REPLACE: break; case SWITCH_ABC_TYPE_READ_REPLACE: break; case SWITCH_ABC_TYPE_READ_PING: break; case SWITCH_ABC_TYPE_CLOSE: if (detector->spandsp_detector) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "(%s) destroying tone detector\n", switch_channel_get_name(channel)); tone_detector_destroy(detector); } break; } return SWITCH_TRUE; }
static void switch_core_standard_on_reset(switch_core_session_t *session) { switch_channel_set_variable(session->channel, "call_uuid", switch_core_session_get_uuid(session)); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard RESET\n", switch_channel_get_name(session->channel)); if (switch_channel_test_flag(session->channel, CF_RECOVERING_BRIDGE)) { switch_core_session_t *other_session = NULL; const char *uuid = switch_core_session_get_uuid(session); if (switch_channel_test_flag(session->channel, CF_BRIDGE_ORIGINATOR)) { const char *other_uuid = switch_channel_get_partner_uuid(session->channel); int x = 0; if (other_uuid) { for (x = 0; other_session == NULL && x < 20; x++) { if (!switch_channel_up(session->channel)) { break; } other_session = switch_core_session_locate(other_uuid); switch_yield(100000); } } if (other_session) { switch_channel_t *other_channel = switch_core_session_get_channel(other_session); switch_channel_clear_flag(session->channel, CF_BRIDGE_ORIGINATOR); switch_channel_wait_for_state_timeout(other_channel, CS_RESET, 5000); switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 2000, NULL); if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) && switch_channel_test_flag(other_channel, CF_PROXY_MODE)) { switch_ivr_signal_bridge(session, other_session); } else { switch_ivr_uuid_bridge(uuid, other_uuid); } switch_core_session_rwunlock(other_session); } } switch_channel_clear_flag(session->channel, CF_RECOVERING_BRIDGE); } }
SWITCH_DECLARE_CONSTRUCTOR CoreSession::CoreSession(switch_core_session_t *new_session) { init_vars(); if (new_session) { session = new_session; channel = switch_core_session_get_channel(session); allocated = 1; switch_core_session_read_lock_hangup(session); uuid = strdup(switch_core_session_get_uuid(session)); } }
void eventpipe_events_handler(switch_event_t *event) { struct eventpipe_call *current = NULL; const char *uuid1 = ""; const char *uuid2 = ""; switch_assert(event != NULL); if ((event->event_id != SWITCH_EVENT_CUSTOM) && (event->event_id != SWITCH_EVENT_DTMF)) { return; } uuid1 = switch_event_get_header(event, "unique-id"); if (zstr(uuid1)) { return; } switch_mutex_lock(globals.eventpipe_call_list_mutex); if (!head) { goto eventpipe_events_handler_done; } if (!head->session) { goto eventpipe_events_handler_done; } current = head; while (current) { if (current->session) { uuid2 = ""; uuid2 = switch_core_session_get_uuid(current->session); /* check if event unique-id is matching a call uuid in eventpipe */ if ((uuid2) && (!zstr(uuid2) && (!strcmp(uuid1, uuid2)))) { /* conference event case */ if (event->event_id == SWITCH_EVENT_CUSTOM) { const char *event_subclass = switch_str_nil(switch_event_get_header(event, "event-subclass")); if (!strcmp(event_subclass, PLIVO_EVENT_CONFERENCE)) { eventpipe_events_on_conference(current->session, event); } /* dtmf event case */ } else if (event->event_id == SWITCH_EVENT_DTMF) { eventpipe_events_on_dtmf(current->session, event); } goto eventpipe_events_handler_done; } } current = current->next; } eventpipe_events_handler_done: switch_mutex_unlock(globals.eventpipe_call_list_mutex); }
SWITCH_DECLARE(int) CoreSession::originate(CoreSession *a_leg_session, char *dest, int timeout, switch_state_handler_table_t *handlers) { switch_core_session_t *aleg_core_session = NULL; this_check(0); cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; if (a_leg_session != NULL) { aleg_core_session = a_leg_session->session; } // this session has no valid switch_core_session_t at this point, and therefore // no valid channel. since the threadstate is stored in the channel, and there // is none, if we try to call begin_alllow_threads it will fail miserably. // use the 'a leg session' to do the thread swapping stuff. if (a_leg_session) a_leg_session->begin_allow_threads(); if (switch_ivr_originate(aleg_core_session, &session, &cause, dest, timeout, handlers, NULL, NULL, NULL, NULL, SOF_NONE, NULL) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Error Creating Outgoing Channel! [%s]\n", dest); goto failed; } if (a_leg_session) a_leg_session->end_allow_threads(); channel = switch_core_session_get_channel(session); allocated = 1; switch_safe_free(uuid); uuid = strdup(switch_core_session_get_uuid(session)); switch_channel_set_state(switch_core_session_get_channel(session), CS_SOFT_EXECUTE); return SWITCH_STATUS_SUCCESS; failed: if (a_leg_session) a_leg_session->end_allow_threads(); return SWITCH_STATUS_FALSE; }
static void perl_function(switch_core_session_t *session, char *data) { char *uuid = switch_core_session_get_uuid(session); PerlInterpreter *my_perl = clone_perl(); char code[1024] = ""; perl_parse(my_perl, xs_init, 3, embedding, NULL); switch_snprintf(code, sizeof(code), "use lib '%s/perl';\n" "use freeswitch;\n" "$SWITCH_ENV{UUID} = \"%s\";\n" "$session = new freeswitch::Session(\"%s\")", SWITCH_GLOBAL_dirs.base_dir, uuid, uuid); perl_parse_and_execute(my_perl, data, code); destroy_perl(&my_perl); }
/** * Process a buffer of audio data for call progress tones * * @param bug the session's media bug * @param user_data the detector * @param type the type of data available from the bug * @return SWITCH_TRUE */ static switch_bool_t callprogress_detector_process_buffer(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) { tone_detector_t *detector = (tone_detector_t *)user_data; switch_core_session_t *session = detector->session; switch(type) { case SWITCH_ABC_TYPE_INIT: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "initializing tone detector\n"); tone_detector_init(detector); break; case SWITCH_ABC_TYPE_READ_REPLACE: { switch_frame_t *frame; const char *detected_tone = NULL; if (!detector->spandsp_detector) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "detector is destroyed\n"); return SWITCH_FALSE; } if (!(frame = switch_core_media_bug_get_read_replace_frame(bug))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "error reading frame\n"); return SWITCH_FALSE; } tone_detector_process_buffer(detector, frame->data, frame->samples, &detected_tone); if (detected_tone) { switch_event_t *event = NULL; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "DETECTED TONE: %s\n", detected_tone); if (switch_event_create(&event, SWITCH_EVENT_DETECTED_TONE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detected-Tone", detected_tone); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(session)); switch_event_fire(&event); } } break; } case SWITCH_ABC_TYPE_CLOSE: if (detector->spandsp_detector) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "destroying tone detector\n"); tone_detector_destroy(detector); } break; default: break; } return SWITCH_TRUE; }
void eventpipe_events_on_conference(switch_core_session_t *session, switch_event_t *event) { char args[8192]; char record_args[8192]; const char *action = switch_str_nil(switch_event_get_header(event, "action")); const char *member_id = switch_str_nil(switch_event_get_header(event, "member-id")); const char *conf_room = switch_str_nil(switch_event_get_header(event, "conference-name")); const char *calluuid = switch_core_session_get_uuid(session); switch_channel_t *channel = switch_core_session_get_channel(session); if (!channel) { return; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Event-Name: %s, Event-Subclass: %s, Conference-Name: %s, Action: %s, Member-ID: %s, Unique-ID: %s\n", switch_str_nil(switch_event_get_header(event, "event-name")), switch_str_nil(switch_event_get_header(event, "event-subclass")), conf_room, action, member_id, calluuid); if (!strcmp(action, "add-member")) { const char *enter_sound = switch_str_nil(switch_channel_get_variable(channel, "eventpipe_conference_enter_sound")); const char *record_file = switch_str_nil(switch_channel_get_variable(channel, "eventpipe_conference_record_file")); switch_channel_set_variable(channel, "eventpipe_conference_member_id", member_id); switch_channel_set_variable(channel, "eventpipe_conference_room", conf_room); if (!zstr(enter_sound)) { switch_snprintf(args, sizeof(args), "%s play %s async", conf_room, enter_sound); eventpipe_execute_api(session, "conference", args); } if (!zstr(record_file)) { switch_snprintf(record_args, sizeof(record_args), "%s record %s", conf_room, record_file); eventpipe_execute_api(session, "conference", record_args); } } else if (!strcmp(action, "del-member")) { const char *exit_sound = switch_str_nil(switch_channel_get_variable(channel, "eventpipe_conference_exit_sound")); switch_channel_set_variable(channel, "eventpipe_conference_member_id", ""); switch_channel_set_variable(channel, "eventpipe_conference_room", ""); switch_channel_set_variable(channel, "eventpipe_conference_record_file", ""); if (!zstr(exit_sound)) { switch_snprintf(args, sizeof(args), "conference %s play %s async", conf_room, exit_sound); eventpipe_execute_api(session, "conference", args); } } }
char *sofia_media_get_multipart(switch_core_session_t *session, const char *prefix, const char *sdp, char **mp_type) { char *extra_headers = NULL; switch_stream_handle_t stream = { 0 }; switch_event_header_t *hi = NULL; int x = 0; switch_channel_t *channel = switch_core_session_get_channel(session); const char *boundary = switch_core_session_get_uuid(session); SWITCH_STANDARD_STREAM(stream); if ((hi = switch_channel_variable_first(channel))) { for (; hi; hi = hi->next) { const char *name = (char *) hi->name; char *value = (char *) hi->value; if (!strncasecmp(name, prefix, strlen(prefix))) { const char *hname = name + strlen(prefix); if (*value == '~') { stream.write_function(&stream, "--%s\nContent-Type: %s\nContent-Length: %d\n%s\n", boundary, hname, strlen(value), value + 1); } else { stream.write_function(&stream, "--%s\nContent-Type: %s\nContent-Length: %d\n\n%s\n", boundary, hname, strlen(value) + 1, value); } x++; } } switch_channel_variable_last(channel); } if (x) { *mp_type = switch_core_session_sprintf(session, "multipart/mixed; boundary=%s", boundary); if (sdp) { stream.write_function(&stream, "--%s\nContent-Type: application/sdp\nContent-Length: %d\n\n%s\n", boundary, strlen(sdp) + 1, sdp); } stream.write_function(&stream, "--%s--\n", boundary); } if (!zstr((char *) stream.data)) { extra_headers = stream.data; } else { switch_safe_free(stream.data); } return extra_headers; }
SWITCH_DECLARE(switch_status_t) switch_core_session_perform_kill_channel(switch_core_session_t *session, const char *file, const char *func, int line, switch_signal_t sig) { switch_io_event_hook_kill_channel_t *ptr; switch_status_t status = SWITCH_STATUS_FALSE; switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_core_session_get_uuid(session), SWITCH_LOG_DEBUG, "Send signal %s [%s]\n", switch_channel_get_name(session->channel), SIG_NAMES[sig]); if (session->endpoint_interface->io_routines->kill_channel) { if ((status = session->endpoint_interface->io_routines->kill_channel(session, sig)) == SWITCH_STATUS_SUCCESS) { for (ptr = session->event_hooks.kill_channel; ptr; ptr = ptr->next) { if ((status = ptr->kill_channel(session, sig)) != SWITCH_STATUS_SUCCESS) { break; } } } } return status; }
static void put_text_msg(void *user_data, const uint8_t *msg, int len) { switch_tdd_t *pvt = (switch_tdd_t *) user_data; switch_event_t *event, *clone; switch_channel_t *channel = switch_core_session_get_channel(pvt->session); switch_core_session_t *other_session; switch_channel_add_variable_var_check(channel, "tdd_messages", (char *)msg, SWITCH_FALSE, SWITCH_STACK_PUSH); if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TDD_RECV_MESSAGE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", "mod_spandsp"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", "tdd"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", "TDD MESSAGE"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "TDD-Data", (char *)msg); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(pvt->session)); switch_event_add_body(event, "%s\n\n", (char *)msg); if (switch_core_session_get_partner(pvt->session, &other_session) == SWITCH_STATUS_SUCCESS) { if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) { switch_core_session_receive_event(other_session, &clone); } if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) { switch_core_session_queue_event(other_session, &clone); } switch_core_session_rwunlock(other_session); } switch_event_fire(&event); } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s got TDD Message [%s]\n", switch_channel_get_name(channel), (char *)msg); }
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); }
static void switch_core_standard_on_execute(switch_core_session_t *session) { switch_caller_extension_t *extension; const char *uuid; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard EXECUTE\n", switch_channel_get_name(session->channel)); switch_channel_set_variable(session->channel, "call_uuid", switch_core_session_get_uuid(session)); if (switch_channel_get_variable(session->channel, "recovered") && !switch_channel_test_flag(session->channel, CF_RECOVERED)) { switch_channel_set_flag(session->channel, CF_RECOVERED); } top: switch_channel_clear_flag(session->channel, CF_RESET); if ((extension = switch_channel_get_caller_extension(session->channel)) == 0) { switch_channel_hangup(session->channel, SWITCH_CAUSE_NORMAL_CLEARING); return; } while (switch_channel_get_state(session->channel) == CS_EXECUTE && extension->current_application) { switch_caller_application_t *current_application = extension->current_application; extension->current_application = extension->current_application->next; if (switch_core_session_execute_application(session, current_application->application_name, current_application->application_data) != SWITCH_STATUS_SUCCESS) { return; } if (switch_channel_test_flag(session->channel, CF_RESET)) { goto top; } } if (switch_channel_ready(session->channel) && switch_channel_get_state(session->channel) == CS_EXECUTE && switch_channel_test_flag(session->channel, CF_CONFIRM_BLIND_TRANSFER) && (uuid = switch_channel_get_variable(session->channel, "blind_transfer_uuid"))) { switch_core_session_t *other_session; if ((other_session = switch_core_session_locate(uuid))) { switch_core_session_message_t msg = { 0 }; msg.message_id = SWITCH_MESSAGE_INDICATE_BLIND_TRANSFER_RESPONSE; msg.from = __FILE__; msg.numeric_arg = 0; switch_core_session_receive_message(other_session, &msg); switch_core_session_rwunlock(other_session); switch_channel_set_variable(session->channel, "park_timeout", "10:blind_transfer"); switch_channel_set_state(session->channel, CS_PARK); switch_channel_clear_flag(session->channel, CF_CONFIRM_BLIND_TRANSFER); } } if (switch_channel_ready(session->channel) && switch_channel_get_state(session->channel) == CS_EXECUTE) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "%s has executed the last dialplan instruction, hanging up.\n", switch_channel_get_name(session->channel)); switch_channel_hangup(session->channel, SWITCH_CAUSE_NORMAL_CLEARING); } }
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); } }
static void switch_core_standard_on_reset(switch_core_session_t *session) { switch_channel_set_variable(session->channel, "call_uuid", switch_core_session_get_uuid(session)); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard RESET\n", switch_channel_get_name(session->channel)); }
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; }
SWITCH_DECLARE(void) switch_log_vprintf(switch_text_channel_t channel, const char *file, const char *func, int line, const char *userdata, switch_log_level_t level, const char *fmt, va_list ap) { char *data = NULL; char *new_fmt = NULL; int ret = 0; FILE *handle; const char *filep = (file ? switch_cut_path(file) : ""); const char *funcp = (func ? func : ""); char *content = NULL; switch_time_t now = switch_micro_time_now(); uint32_t len; #ifdef SWITCH_FUNC_IN_LOG const char *extra_fmt = "%s [%s] %s:%d %s()%c%s"; #else const char *extra_fmt = "%s [%s] %s:%d%c%s"; #endif switch_log_level_t limit_level = runtime.hard_log_level; if (channel == SWITCH_CHANNEL_ID_SESSION && userdata) { switch_core_session_t *session = (switch_core_session_t *) userdata; if (limit_level < session->loglevel) { limit_level = session->loglevel; } } if (level > 100) { if ((uint32_t) (level - 100) > runtime.debug_level) { return; } level = 7; } if (level > limit_level) { return; } switch_assert(level < SWITCH_LOG_INVALID); handle = switch_core_data_channel(channel); if (channel != SWITCH_CHANNEL_ID_LOG_CLEAN) { char date[80] = ""; //switch_size_t retsize; switch_time_exp_t tm; switch_time_exp_lt(&tm, now); switch_snprintf(date, sizeof(date), "%0.4d-%0.2d-%0.2d %0.2d:%0.2d:%0.2d.%0.6d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec); //switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); #ifdef SWITCH_FUNC_IN_LOG len = (uint32_t) (strlen(extra_fmt) + strlen(date) + strlen(filep) + 32 + strlen(funcp) + strlen(fmt)); #else len = (uint32_t) (strlen(extra_fmt) + strlen(date) + strlen(filep) + 32 + strlen(fmt)); #endif new_fmt = malloc(len + 1); switch_assert(new_fmt); #ifdef SWITCH_FUNC_IN_LOG switch_snprintf(new_fmt, len, extra_fmt, date, switch_log_level2str(level), filep, line, funcp, 128, fmt); #else switch_snprintf(new_fmt, len, extra_fmt, date, switch_log_level2str(level), filep, line, 128, fmt); #endif fmt = new_fmt; } ret = switch_vasprintf(&data, fmt, ap); if (ret == -1) { fprintf(stderr, "Memory Error\n"); goto end; } if (channel == SWITCH_CHANNEL_ID_LOG_CLEAN) { content = data; } else { if ((content = strchr(data, 128))) { *content = ' '; } } if (channel == SWITCH_CHANNEL_ID_EVENT) { switch_event_t *event; if (switch_event_running() == SWITCH_STATUS_SUCCESS && switch_event_create(&event, SWITCH_EVENT_LOG) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Log-Data", data); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Log-File", filep); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Log-Function", funcp); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Log-Line", "%d", line); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Log-Level", "%d", (int) level); if (!zstr(userdata)) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "User-Data", userdata); } switch_event_fire(&event); data = NULL; } goto end; } if (console_mods_loaded == 0 || !do_mods) { if (handle) { int aok = 1; #ifndef WIN32 fd_set can_write; int fd; struct timeval to; fd = fileno(handle); memset(&to, 0, sizeof(to)); FD_ZERO(&can_write); FD_SET(fd, &can_write); to.tv_sec = 0; to.tv_usec = 100000; if (select(fd + 1, NULL, &can_write, NULL, &to) > 0) { aok = FD_ISSET(fd, &can_write); } else { aok = 0; } #endif if (aok) { if (COLORIZE) { #ifdef WIN32 SetConsoleTextAttribute(hStdout, COLORS[level]); WriteFile(hStdout, data, (DWORD) strlen(data), NULL, NULL); SetConsoleTextAttribute(hStdout, wOldColorAttrs); #else fprintf(handle, "%s%s%s", COLORS[level], data, SWITCH_SEQ_DEFAULT_COLOR); #endif } else { fprintf(handle, "%s", data); } } } } if (do_mods && level <= MAX_LEVEL) { switch_log_node_t *node = switch_log_node_alloc(); node->data = data; data = NULL; switch_set_string(node->file, filep); switch_set_string(node->func, funcp); node->line = line; node->level = level; node->content = content; node->timestamp = now; node->channel = channel; if (channel == SWITCH_CHANNEL_ID_SESSION) { node->userdata = userdata ? strdup(switch_core_session_get_uuid((switch_core_session_t *) userdata)) : NULL; } else { node->userdata = !zstr(userdata) ? strdup(userdata) : NULL; } if (switch_queue_trypush(LOG_QUEUE, node) != SWITCH_STATUS_SUCCESS) { switch_log_node_free(&node); } } end: switch_safe_free(data); switch_safe_free(new_fmt); }
static switch_status_t my_on_reporting(switch_core_session_t *session) { cJSON *json_cdr = NULL; char *json_text = NULL; char *path = NULL; char *curl_json_text = NULL; const char *logdir = NULL; char *json_text_escaped = NULL; int fd = -1, err_dir_index; uint32_t cur_try; long httpRes; CURL *curl_handle = NULL; switch_curl_slist_t *headers = NULL; switch_curl_slist_t *slist = NULL; switch_channel_t *channel = switch_core_session_get_channel(session); switch_status_t status = SWITCH_STATUS_FALSE; int is_b; const char *a_prefix = ""; if (globals.shutdown) { return SWITCH_STATUS_SUCCESS; } is_b = channel && switch_channel_get_originator_caller_profile(channel); if (!globals.log_b && is_b) { const char *force_cdr = switch_channel_get_variable(channel, SWITCH_FORCE_PROCESS_CDR_VARIABLE); if (!switch_true(force_cdr)) { return SWITCH_STATUS_SUCCESS; } } if (!is_b && globals.prefix_a) a_prefix = "a_"; if (switch_ivr_generate_json_cdr(session, &json_cdr, globals.encode_values == ENCODING_DEFAULT) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Generating Data!\n"); return SWITCH_STATUS_FALSE; } json_text = cJSON_PrintUnformatted(json_cdr); if (!json_text) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); goto error; } switch_thread_rwlock_rdlock(globals.log_path_lock); if (!(logdir = switch_channel_get_variable(channel, "json_cdr_base"))) { logdir = globals.log_dir; } if (!zstr(logdir) && (globals.log_http_and_disk || !globals.url_count)) { path = switch_mprintf("%s%s%s%s.cdr.json", logdir, SWITCH_PATH_SEPARATOR, a_prefix, switch_core_session_get_uuid(session)); switch_thread_rwlock_unlock(globals.log_path_lock); if (path) { #ifdef _MSC_VER if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) { #else if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) > -1) { #endif int wrote; wrote = write(fd, json_text, (unsigned) strlen(json_text)); close(fd); fd = -1; if(wrote < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error writing [%s]\n",path); } } else { char ebuf[512] = { 0 }; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error writing [%s][%s]\n", path, switch_strerror_r(errno, ebuf, sizeof(ebuf))); } switch_safe_free(path); } } else { switch_thread_rwlock_unlock(globals.log_path_lock); } /* try to post it to the web server */ if (globals.url_count) { char *destUrl = NULL; curl_handle = switch_curl_easy_init(); if (globals.encode) { switch_size_t need_bytes = strlen(json_text) * 3; json_text_escaped = malloc(need_bytes); switch_assert(json_text_escaped); memset(json_text_escaped, 0, need_bytes); if (globals.encode == ENCODING_DEFAULT) { headers = switch_curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded"); switch_url_encode(json_text, json_text_escaped, need_bytes); } else { headers = switch_curl_slist_append(headers, "Content-Type: application/x-www-form-base64-encoded"); switch_b64_encode((unsigned char *) json_text, need_bytes / 3, (unsigned char *) json_text_escaped, need_bytes); } switch_safe_free(json_text); json_text = json_text_escaped; if (!(curl_json_text = switch_mprintf("cdr=%s", json_text))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); goto error; } } else { headers = switch_curl_slist_append(headers, "Content-Type: application/json"); curl_json_text = (char *)json_text; } if (!zstr(globals.cred)) { switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, globals.auth_scheme); switch_curl_easy_setopt(curl_handle, CURLOPT_USERPWD, globals.cred); } switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers); switch_curl_easy_setopt(curl_handle, CURLOPT_POST, 1); switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1); switch_curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, curl_json_text); switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-json/1.0"); switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, httpCallBack); if (globals.disable100continue) { slist = switch_curl_slist_append(slist, "Expect:"); switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, slist); } if (globals.ssl_cert_file) { switch_curl_easy_setopt(curl_handle, CURLOPT_SSLCERT, globals.ssl_cert_file); } if (globals.ssl_key_file) { switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEY, globals.ssl_key_file); } if (globals.ssl_key_password) { switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEYPASSWD, globals.ssl_key_password); } if (globals.ssl_version) { if (!strcasecmp(globals.ssl_version, "SSLv3")) { switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3); } else if (!strcasecmp(globals.ssl_version, "TLSv1")) { switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); } } if (globals.ssl_cacert_file) { switch_curl_easy_setopt(curl_handle, CURLOPT_CAINFO, globals.ssl_cacert_file); } /* these were used for testing, optionally they may be enabled if someone desires switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 120); // tcp timeout switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); // 302 recursion level */ for (cur_try = 0; cur_try < globals.retries; cur_try++) { if (cur_try > 0) { switch_yield(globals.delay * 1000000); } destUrl = switch_mprintf("%s?uuid=%s", globals.urls[globals.url_index], switch_core_session_get_uuid(session)); switch_curl_easy_setopt(curl_handle, CURLOPT_URL, destUrl); if (!strncasecmp(destUrl, "https", 5)) { switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0); switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0); } if (globals.enable_cacert_check) { switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, TRUE); } if (globals.enable_ssl_verifyhost) { switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 2); } switch_curl_easy_perform(curl_handle); switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes); switch_safe_free(destUrl); if (httpRes >= 200 && httpRes < 300) { goto success; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Got error [%ld] posting to web server [%s]\n", httpRes, globals.urls[globals.url_index]); globals.url_index++; switch_assert(globals.url_count <= MAX_URLS); if (globals.url_index >= globals.url_count) { globals.url_index = 0; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Retry will be with url [%s]\n", globals.urls[globals.url_index]); } } switch_curl_easy_cleanup(curl_handle); switch_curl_slist_free_all(headers); switch_curl_slist_free_all(slist); slist = NULL; headers = NULL; curl_handle = NULL; /* if we are here the web post failed for some reason */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to post to web server, writing to file\n"); for (err_dir_index = 0; err_dir_index < globals.err_dir_count; err_dir_index++) { switch_thread_rwlock_rdlock(globals.log_path_lock); path = switch_mprintf("%s%s%s%s.cdr.json", globals.err_log_dir[err_dir_index], SWITCH_PATH_SEPARATOR, a_prefix, switch_core_session_get_uuid(session)); switch_thread_rwlock_unlock(globals.log_path_lock); if (path) { #ifdef _MSC_VER if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) { #else if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) > -1) { #endif int wrote; wrote = write(fd, json_text, (unsigned) strlen(json_text)); close(fd); fd = -1; if(wrote < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error writing [%s]\n",path); } break; } else { char ebuf[512] = { 0 }; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s! [%s]\n", path, switch_strerror_r(errno, ebuf, sizeof(ebuf))); } switch_safe_free(path); } } } success: status = SWITCH_STATUS_SUCCESS; error: if (curl_handle) { switch_curl_easy_cleanup(curl_handle); } if (headers) { switch_curl_slist_free_all(headers); } if (slist) { switch_curl_slist_free_all(slist); } if (curl_json_text != json_text) { switch_safe_free(curl_json_text); } cJSON_Delete(json_cdr); switch_safe_free(json_text); return status; } static void event_handler(switch_event_t *event) { const char *sig = switch_event_get_header(event, "Trapped-Signal"); if (sig && !strcmp(sig, "HUP")) { if (globals.rotate) { set_json_cdr_log_dirs(); } } } static switch_state_handler_table_t state_handlers = { /*.on_init */ NULL, /*.on_routing */ NULL, /*.on_execute */ NULL, /*.on_hangup */ NULL, /*.on_exchange_media */ NULL, /*.on_soft_execute */ NULL, /*.on_consume_media */ NULL, /*.on_hibernate */ NULL, /*.on_reset */ NULL, /*.on_park */ NULL, /*.on_reporting */ my_on_reporting }; SWITCH_MODULE_LOAD_FUNCTION(mod_json_cdr_load) { char *cf = "json_cdr.conf"; switch_xml_t cfg, xml, settings, param; switch_status_t status = SWITCH_STATUS_SUCCESS; /* test global state handlers */ switch_core_add_state_handler(&state_handlers); *module_interface = switch_loadable_module_create_module_interface(pool, modname); memset(&globals, 0, sizeof(globals)); if (switch_event_bind_removable(modname, SWITCH_EVENT_TRAP, SWITCH_EVENT_SUBCLASS_ANY, event_handler, NULL, &globals.node) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); return SWITCH_STATUS_GENERR; } globals.log_http_and_disk = 0; globals.log_b = 1; globals.disable100continue = 0; globals.pool = pool; globals.auth_scheme = CURLAUTH_BASIC; globals.encode_values = ENCODING_DEFAULT; switch_thread_rwlock_create(&globals.log_path_lock, pool); /* parse the config */ if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf); return SWITCH_STATUS_TERM; } if ((settings = switch_xml_child(cfg, "settings"))) { for (param = switch_xml_child(settings, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); char *val = (char *) switch_xml_attr_soft(param, "value"); if (!strcasecmp(var, "cred") && !zstr(val)) { globals.cred = switch_core_strdup(globals.pool, val); } else if (!strcasecmp(var, "url") && !zstr(val)) { if (globals.url_count >= MAX_URLS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "maximum urls configured!\n"); } else { globals.urls[globals.url_count++] = switch_core_strdup(globals.pool, val); } } else if (!strcasecmp(var, "log-http-and-disk")) { globals.log_http_and_disk = switch_true(val); } else if (!strcasecmp(var, "delay") && !zstr(val)) { globals.delay = (uint32_t) atoi(val); } else if (!strcasecmp(var, "log-b-leg")) { globals.log_b = switch_true(val); } else if (!strcasecmp(var, "prefix-a-leg")) { globals.prefix_a = switch_true(val); } else if (!strcasecmp(var, "disable-100-continue") && switch_true(val)) { globals.disable100continue = 1; } else if (!strcasecmp(var, "encode") && !zstr(val)) { if (!strcasecmp(val, "base64")) { globals.encode = ENCODING_BASE64; } else { globals.encode = switch_true(val) ? ENCODING_DEFAULT : ENCODING_NONE; } } else if (!strcasecmp(var, "retries") && !zstr(val)) { globals.retries = (uint32_t) atoi(val); } else if (!strcasecmp(var, "rotate") && !zstr(val)) { globals.rotate = switch_true(val); } else if (!strcasecmp(var, "log-dir")) { if (zstr(val)) { globals.base_log_dir = switch_core_sprintf(globals.pool, "%s%sjson_cdr", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR); } else { if (switch_is_file_path(val)) { globals.base_log_dir = switch_core_strdup(globals.pool, val); } else { globals.base_log_dir = switch_core_sprintf(globals.pool, "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, val); } } } else if (!strcasecmp(var, "err-log-dir")) { if (globals.err_dir_count >= MAX_ERR_DIRS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "maximum error directories configured!\n"); } else { if (zstr(val)) { globals.base_err_log_dir[globals.err_dir_count++] = switch_core_sprintf(globals.pool, "%s%sjson_cdr", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR); } else { if (switch_is_file_path(val)) { globals.base_err_log_dir[globals.err_dir_count++] = switch_core_strdup(globals.pool, val); } else { globals.base_err_log_dir[globals.err_dir_count++] = switch_core_sprintf(globals.pool, "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, val); } } } } else if (!strcasecmp(var, "enable-cacert-check") && switch_true(val)) { globals.enable_cacert_check = 1; } else if (!strcasecmp(var, "ssl-cert-path")) { globals.ssl_cert_file = switch_core_strdup(globals.pool, val); } else if (!strcasecmp(var, "ssl-key-path")) { globals.ssl_key_file = switch_core_strdup(globals.pool, val); } else if (!strcasecmp(var, "ssl-key-password")) { globals.ssl_key_password = switch_core_strdup(globals.pool, val); } else if (!strcasecmp(var, "ssl-version")) { globals.ssl_version = switch_core_strdup(globals.pool, val); } else if (!strcasecmp(var, "ssl-cacert-file")) { globals.ssl_cacert_file = switch_core_strdup(globals.pool, val); } else if (!strcasecmp(var, "enable-ssl-verifyhost") && switch_true(val)) { globals.enable_ssl_verifyhost = 1; } else if (!strcasecmp(var, "auth-scheme")) { if (*val == '=') { globals.auth_scheme = 0; val++; } if (!strcasecmp(val, "basic")) { globals.auth_scheme |= CURLAUTH_BASIC; } else if (!strcasecmp(val, "digest")) { globals.auth_scheme |= CURLAUTH_DIGEST; } else if (!strcasecmp(val, "NTLM")) { globals.auth_scheme |= CURLAUTH_NTLM; } else if (!strcasecmp(val, "GSS-NEGOTIATE")) { globals.auth_scheme |= CURLAUTH_GSSNEGOTIATE; } else if (!strcasecmp(val, "any")) { globals.auth_scheme = CURLAUTH_ANY; } } else if (!strcasecmp(var, "encode-values") && !zstr(val)) { globals.encode_values = switch_true(val) ? ENCODING_DEFAULT : ENCODING_NONE; } } if (!globals.err_dir_count) { if (!zstr(globals.base_log_dir)) { globals.base_err_log_dir[globals.err_dir_count++] = switch_core_strdup(globals.pool, globals.base_log_dir); } else { globals.base_err_log_dir[globals.err_dir_count++] = switch_core_sprintf(globals.pool, "%s%sjson_cdr", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR); } } } if (globals.retries && !globals.delay) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Retries set but delay 0 setting to 5 seconds\n"); globals.delay = 5; } globals.retries++; set_json_cdr_log_dirs(); switch_xml_free(xml); return status; } SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_json_cdr_shutdown) { int err_dir_index = 0; globals.shutdown = 1; switch_safe_free(globals.log_dir); for (;err_dir_index < globals.err_dir_count; err_dir_index++) { switch_safe_free(globals.err_log_dir[err_dir_index]); } switch_event_unbind(&globals.node); switch_core_remove_state_handler(&state_handlers); switch_thread_rwlock_destroy(globals.log_path_lock); return SWITCH_STATUS_SUCCESS; }
/* State methods they get called when the state changes to the specific state returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it. */ static switch_status_t channel_on_init(switch_core_session_t *session) { switch_channel_t *channel, *b_channel; private_t *tech_pvt = NULL, *b_tech_pvt = NULL; switch_core_session_t *b_session; char name[128]; switch_caller_profile_t *caller_profile; tech_pvt = switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); channel = switch_core_session_get_channel(session); switch_assert(channel != NULL); if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND) && !switch_test_flag(tech_pvt, TFLAG_BLEG)) { if (!(b_session = switch_core_session_request(loopback_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, NULL))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failure.\n"); goto end; } if (switch_core_session_read_lock(b_session) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failure.\n"); switch_core_session_destroy(&b_session); goto end; } switch_core_session_add_stream(b_session, NULL); b_channel = switch_core_session_get_channel(b_session); b_tech_pvt = (private_t *) switch_core_session_alloc(b_session, sizeof(*b_tech_pvt)); switch_snprintf(name, sizeof(name), "loopback/%s-b", tech_pvt->caller_profile->destination_number); switch_channel_set_name(b_channel, name); if (tech_init(b_tech_pvt, b_session, switch_core_session_get_read_codec(session)) != SWITCH_STATUS_SUCCESS) { switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); switch_core_session_destroy(&b_session); goto end; } caller_profile = switch_caller_profile_clone(b_session, tech_pvt->caller_profile); caller_profile->source = switch_core_strdup(caller_profile->pool, modname); switch_channel_set_caller_profile(b_channel, caller_profile); b_tech_pvt->caller_profile = caller_profile; switch_channel_set_state(b_channel, CS_INIT); tech_pvt->other_session = b_session; tech_pvt->other_tech_pvt = b_tech_pvt; tech_pvt->other_channel = b_channel; //b_tech_pvt->other_session = session; //b_tech_pvt->other_tech_pvt = tech_pvt; //b_tech_pvt->other_channel = channel; b_tech_pvt->other_uuid = switch_core_session_strdup(b_session, switch_core_session_get_uuid(session)); switch_set_flag_locked(tech_pvt, TFLAG_LINKED); switch_set_flag_locked(b_tech_pvt, TFLAG_LINKED); switch_set_flag_locked(b_tech_pvt, TFLAG_BLEG); switch_channel_set_flag(channel, CF_ACCEPT_CNG); //switch_ivr_transfer_variable(session, tech_pvt->other_session, "process_cdr"); switch_ivr_transfer_variable(session, tech_pvt->other_session, NULL); switch_channel_set_variable(channel, "other_loopback_leg_uuid", switch_channel_get_uuid(b_channel)); switch_channel_set_variable(b_channel, "other_loopback_leg_uuid", switch_channel_get_uuid(channel)); if (switch_core_session_thread_launch(b_session) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error spawning thread\n"); switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); goto end; } } else if ((tech_pvt->other_session = switch_core_session_locate(tech_pvt->other_uuid))) { tech_pvt->other_tech_pvt = switch_core_session_get_private(tech_pvt->other_session); tech_pvt->other_channel = switch_core_session_get_channel(tech_pvt->other_session); } if (!tech_pvt->other_session) { switch_clear_flag_locked(tech_pvt, TFLAG_LINKED); switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); goto end; } switch_channel_set_variable(channel, "loopback_leg", switch_test_flag(tech_pvt, TFLAG_BLEG) ? "B" : "A"); switch_channel_set_state(channel, CS_ROUTING); end: return SWITCH_STATUS_SUCCESS; }
/* This is where we actually charge the guy This can be called anytime a call is in progress or at the end of a call before the session is destroyed */ static switch_status_t do_billing(switch_core_session_t *session) { /* FS vars we will use */ switch_channel_t *channel; switch_caller_profile_t *profile; /* Local vars */ nibble_data_t *nibble_data; switch_time_t ts = switch_micro_time_now(); double billamount; char date[80] = ""; char *uuid; switch_size_t retsize; switch_time_exp_t tm; const char *billrate; const char *billincrement; const char *billaccount; double nobal_amt = globals.nobal_amt; double lowbal_amt = globals.lowbal_amt; double balance; if (!session) { /* Why are we here? */ return SWITCH_STATUS_SUCCESS; } uuid = switch_core_session_get_uuid(session); /* Get channel var */ if (!(channel = switch_core_session_get_channel(session))) { return SWITCH_STATUS_SUCCESS; } /* Variables kept in FS but relevant only to this module */ billrate = switch_channel_get_variable(channel, "nibble_rate"); billincrement = switch_channel_get_variable(channel, "nibble_increment"); billaccount = switch_channel_get_variable(channel, "nibble_account"); if (!zstr(switch_channel_get_variable(channel, "nobal_amt"))) { nobal_amt = atof(switch_channel_get_variable(channel, "nobal_amt")); } if (!zstr(switch_channel_get_variable(channel, "lowbal_amt"))) { lowbal_amt = atof(switch_channel_get_variable(channel, "lowbal_amt")); } /* Return if there's no billing information on this session */ if (!billrate || !billaccount) { return SWITCH_STATUS_SUCCESS; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Attempting to bill at $%s per minute to account %s\n", billrate, billaccount); /* Get caller profile info from channel */ profile = switch_channel_get_caller_profile(channel); if (!profile || !profile->times) { /* No caller profile (why would this happen?) */ return SWITCH_STATUS_SUCCESS; } if (profile->times->answered < 1) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Not billing %s - call is not in answered state\n", billaccount); /* See if this person has enough money left to continue the call */ balance = get_balance(billaccount, channel); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Comparing %f to hangup balance of %f\n", balance, nobal_amt); if (balance <= nobal_amt) { /* Not enough money - reroute call to nobal location */ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Balance of %f fell below allowed amount of %f! (Account %s)\n", balance, nobal_amt, billaccount); transfer_call(session, globals.nobal_action); } return SWITCH_STATUS_SUCCESS; } /* Lock this session's data for this module while we tinker with it */ if (globals.mutex) { switch_mutex_lock(globals.mutex); } /* Get our nibble data var. This will be NULL if it's our first call here for this session */ nibble_data = (nibble_data_t *) switch_channel_get_private(channel, "_nibble_data_"); /* Are we in paused mode? If so, we don't do anything here - go back! */ if (nibble_data && (nibble_data->pausets > 0)) { if (globals.mutex) { switch_mutex_unlock(globals.mutex); } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Received heartbeat, but we're paused - ignoring\n"); return SWITCH_STATUS_SUCCESS; } /* Have we done any billing on this channel yet? If no, set up vars for doing so */ if (!nibble_data) { nibble_data = switch_core_session_alloc(session, sizeof(*nibble_data)); memset(nibble_data, 0, sizeof(*nibble_data)); /* Setup new billing data (based on call answer time, in case this module started late with active calls) */ nibble_data->lastts = profile->times->answered; /* Set the initial answer time to match when the call was really answered */ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Beginning new billing on %s\n", uuid); } switch_time_exp_lt(&tm, nibble_data->lastts); switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%d seconds passed since last bill time of %s\n", (int) ((ts - nibble_data->lastts) / 1000000), date); if ((ts - nibble_data->lastts) >= 0) { /* If billincrement is set we bill by it and not by time elapsed */ if (!(switch_strlen_zero(billincrement))) { switch_time_t chargedunits = (ts - nibble_data->lastts) / 1000000 <= atol(billincrement) ? atol(billincrement) * 1000000 : (switch_time_t)(ceil((ts - nibble_data->lastts) / (atol(billincrement) * 1000000.0))) * atol(billincrement) * 1000000; billamount = (atof(billrate) / 1000000 / 60) * chargedunits - nibble_data->bill_adjustments; /* Account for the prepaid amount */ nibble_data->lastts += chargedunits; } else { /* Convert billrate into microseconds and multiply by # of microseconds that have passed since last *successful* bill */ billamount = (atof(billrate) / 1000000 / 60) * ((ts - nibble_data->lastts)) - nibble_data->bill_adjustments; /* Update the last time we billed */ nibble_data->lastts = ts; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Billing $%f to %s (Call: %s / %f so far)\n", billamount, billaccount, uuid, nibble_data->total); /* DO ODBC BILLING HERE and reset counters if it's successful! */ if (bill_event(billamount, billaccount, channel) == SWITCH_STATUS_SUCCESS) { /* Increment total cost */ nibble_data->total += billamount; /* Reset manual billing adjustments from pausing */ nibble_data->bill_adjustments = 0; /* Update channel variable with current billing */ switch_channel_set_variable_printf(channel, "nibble_total_billed", "%f", nibble_data->total); } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failed to log to database!\n"); } } else { if (switch_strlen_zero(billincrement)) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Just tried to bill %s negative minutes! That should be impossible.\n", uuid); } /* Save this location */ if (channel) { switch_channel_set_private(channel, "_nibble_data_", nibble_data); /* don't verify balance and transfer to nobal if we're done with call */ if (switch_channel_get_state(channel) != CS_REPORTING && switch_channel_get_state(channel) != CS_HANGUP) { balance = get_balance(billaccount, channel); /* See if we've achieved low balance */ if (!nibble_data->lowbal_action_executed && balance <= lowbal_amt) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Balance of %f fell below low balance amount of %f! (Account %s)\n", balance, lowbal_amt, billaccount); if (exec_app(session, globals.lowbal_action) != SWITCH_STATUS_SUCCESS) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Low balance action didn't execute\n"); else nibble_data->lowbal_action_executed = 1; } /* See if this person has enough money left to continue the call */ if (balance <= nobal_amt) { /* Not enough money - reroute call to nobal location */ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Balance of %f fell below allowed amount of %f! (Account %s)\n", balance, nobal_amt, billaccount); /* IMPORTANT: Billing must be paused before the transfer occurs! This prevents infinite loops, since the transfer will result */ /* in nibblebill checking the call again in the routing process for an allowed balance! */ /* If you intend to give the user the option to re-up their balance, you must clear & resume billing once the balance is updated! */ nibblebill_pause(session); transfer_call(session, globals.nobal_action); } } } /* Done changing - release lock */ if (globals.mutex) { switch_mutex_unlock(globals.mutex); } /* Go check if this call is allowed to continue */ return SWITCH_STATUS_SUCCESS; }
/** * Start execution of call receivefax component * @param call the call to receive fax from * @param msg the original request * @param session_data the call's session */ static iks *start_receivefax_component(struct rayo_actor *call, struct rayo_message *msg, void *session_data) { iks *iq = msg->payload; switch_core_session_t *session = (switch_core_session_t *)session_data; struct receivefax_component *receivefax_component = NULL; iks *receivefax = iks_find(iq, "receivefax"); iks *response = NULL; switch_event_t *execute_event = NULL; switch_channel_t *channel = switch_core_session_get_channel(session); switch_memory_pool_t *pool; int file_no; /* validate attributes */ if (!VALIDATE_RAYO_RECEIVEFAX(receivefax)) { return iks_new_error(iq, STANZA_ERROR_BAD_REQUEST); } /* fax is only allowed if the call is not currently joined */ if (rayo_call_is_joined(RAYO_CALL(call))) { return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "can't receive fax on a joined call"); } if (rayo_call_is_faxing(RAYO_CALL(call))) { return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "fax already in progress"); } /* create receivefax component */ switch_core_new_memory_pool(&pool); receivefax_component = switch_core_alloc(pool, sizeof(*receivefax_component)); rayo_component_init((struct rayo_component *)receivefax_component, pool, RAT_CALL_COMPONENT, "receivefax", NULL, call, iks_find_attrib(iq, "from")); file_no = rayo_actor_seq_next(call); receivefax_component->filename = switch_core_sprintf(pool, "%s%s%s-%d.tif", globals.file_prefix, SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session), file_no); if (!strncmp(receivefax_component->filename, "http://", 7) || !strncmp(receivefax_component->filename, "https://", 8)) { /* This is an HTTP URL, need to PUT after fax is received */ receivefax_component->local_filename = switch_core_sprintf(pool, "%s%s%s-%d", SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session), file_no); receivefax_component->http_put_after_receive = 1; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s save fax to HTTP URL\n", RAYO_JID(receivefax_component)); } else { /* assume file.. */ receivefax_component->local_filename = receivefax_component->filename; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s save fax to local file\n", RAYO_JID(receivefax_component)); } /* add channel variable so that fax component can be located from fax events */ switch_channel_set_variable(channel, "rayo_fax_jid", RAYO_JID(receivefax_component)); /* clear fax result variables */ switch_channel_set_variable(channel, "fax_success", NULL); switch_channel_set_variable(channel, "fax_result_code", NULL); switch_channel_set_variable(channel, "fax_result_text", NULL); switch_channel_set_variable(channel, "fax_document_transferred_pages", NULL); switch_channel_set_variable(channel, "fax_document_total_pages", NULL); switch_channel_set_variable(channel, "fax_image_resolution", NULL); switch_channel_set_variable(channel, "fax_image_size", NULL); switch_channel_set_variable(channel, "fax_bad_rows", NULL); switch_channel_set_variable(channel, "fax_transfer_rate", NULL); switch_channel_set_variable(channel, "fax_ecm_used", NULL); switch_channel_set_variable(channel, "fax_local_station_id", NULL); switch_channel_set_variable(channel, "fax_remote_station_id", NULL); /* clear fax interrupt variable */ switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_read_frame_interrupt", NULL); rayo_call_set_faxing(RAYO_CALL(call), 1); /* execute rxfax APP */ if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", "rxfax"); switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", receivefax_component->local_filename); if (!switch_channel_test_flag(channel, CF_PROXY_MODE)) { switch_channel_set_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA); } if (switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to rxfax (queue event failed)"); if (execute_event) { switch_event_destroy(&execute_event); } rayo_call_set_faxing(RAYO_CALL(call), 0); RAYO_UNLOCK(receivefax_component); } else { /* component starting... */ rayo_component_send_start(RAYO_COMPONENT(receivefax_component), iq); } } else { response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to create rxfax event"); rayo_call_set_faxing(RAYO_CALL(call), 0); RAYO_UNLOCK(receivefax_component); } return response; }
static switch_status_t populate_database(switch_core_session_t *session, dir_profile_t *profile, const char *domain_name) { switch_status_t status = SWITCH_STATUS_SUCCESS; char *sql = NULL; char *sqlvalues = NULL; char *sqltmp = NULL; int count = 0; switch_xml_t xml_root = NULL, x_domain; switch_xml_t ut; switch_event_t *xml_params = NULL; switch_xml_t group = NULL, groups = NULL, users = NULL, x_params = NULL, x_param = NULL, x_vars = NULL, x_var = NULL; switch_event_create(&xml_params, SWITCH_EVENT_REQUEST_PARAMS); switch_assert(xml_params); if (switch_xml_locate_domain(domain_name, xml_params, &xml_root, &x_domain) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot locate domain %s\n", domain_name); status = SWITCH_STATUS_FALSE; goto end; } if ((groups = switch_xml_child(x_domain, "groups"))) { for (group = switch_xml_child(groups, "group"); group; group = group->next) { if ((users = switch_xml_child(group, "users"))) { for (ut = switch_xml_child(users, "user"); ut; ut = ut->next) { int name_visible = 1; int exten_visible = 1; const char *type = switch_xml_attr_soft(ut, "type"); const char *id = switch_xml_attr_soft(ut, "id"); char *fullName = NULL; char *caller_name = NULL; char *caller_name_override = NULL; char *firstName = NULL; char *lastName = NULL; char *fullNameDigit = NULL; char *firstNameDigit = NULL; char *lastNameDigit = NULL; if (!strcasecmp(type, "pointer")) { continue; } /* Check all the user params */ if ((x_params = switch_xml_child(ut, "params"))) { for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) { const char *var = switch_xml_attr_soft(x_param, "name"); const char *val = switch_xml_attr_soft(x_param, "value"); if (!strcasecmp(var, "directory-visible")) { name_visible = switch_true(val); } if (!strcasecmp(var, "directory-exten-visible")) { exten_visible = switch_true(val); } } } /* Check all the user variables */ if ((x_vars = switch_xml_child(ut, "variables"))) { for (x_var = switch_xml_child(x_vars, "variable"); x_var; x_var = x_var->next) { const char *var = switch_xml_attr_soft(x_var, "name"); const char *val = switch_xml_attr_soft(x_var, "value"); if (!strcasecmp(var, "effective_caller_id_name")) { caller_name = switch_core_session_strdup(session, val); } if (!strcasecmp(var, "directory_full_name")) { caller_name_override = switch_core_session_strdup(session, val); } } } if (caller_name_override) { fullName = caller_name_override; } else { fullName = caller_name; } if (zstr(fullName)) { continue; } firstName = switch_core_session_strdup(session, fullName); if ((lastName = strrchr(firstName, ' '))) { *lastName++ = '\0'; } else { lastName = switch_core_session_strdup(session, firstName); } /* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "FullName %s firstName [%s] lastName [%s]\n", fullName, firstName, lastName); */ /* Generate Digits key mapping */ fullNameDigit = string_to_keypad_digit(fullName); lastNameDigit = string_to_keypad_digit(lastName); firstNameDigit = string_to_keypad_digit(firstName); /* add user into DB */ sql = switch_mprintf("insert into directory_search values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%d','%d')", globals.hostname, switch_core_session_get_uuid(session), id, fullName, fullNameDigit, firstName, firstNameDigit, lastName, lastNameDigit, name_visible, exten_visible); if (sqlvalues) { sqltmp = sqlvalues; sqlvalues = switch_mprintf("%s;%s", sqlvalues, sql); switch_safe_free(sqltmp); } else { sqlvalues = sql; sql = NULL; } switch_safe_free(sql); switch_safe_free(fullNameDigit); switch_safe_free(lastNameDigit); switch_safe_free(firstNameDigit); if (++count >= 100) { count = 0; sql = switch_mprintf("BEGIN;%s;COMMIT;", sqlvalues); directory_execute_sql(sql, globals.mutex); switch_safe_free(sql); switch_safe_free(sqlvalues); } } } } } if (sqlvalues) { sql = switch_mprintf("BEGIN;%s;COMMIT;", sqlvalues); directory_execute_sql(sql, globals.mutex); } end: switch_safe_free(sql); switch_safe_free(sqlvalues); switch_event_destroy(&xml_params); switch_xml_free(xml_root); return status; }
/** * Start CPA */ iks *rayo_cpa_component_start(struct rayo_actor *call, struct rayo_message *msg, void *session_data) { iks *iq = msg->payload; switch_core_session_t *session = (switch_core_session_t *)session_data; iks *input = iks_find(iq, "input"); switch_memory_pool_t *pool = NULL; struct cpa_component *component = NULL; int have_grammar = 0; iks *grammar = NULL; /* create CPA component */ switch_core_new_memory_pool(&pool); component = switch_core_alloc(pool, sizeof(*component)); component = CPA_COMPONENT(rayo_component_init((struct rayo_component *)component, pool, RAT_CALL_COMPONENT, "cpa", NULL, call, iks_find_attrib(iq, "from"))); if (!component) { switch_core_destroy_memory_pool(&pool); return iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "Failed to create CPA entity"); } switch_core_hash_init(&component->signals); /* start CPA detectors */ for (grammar = iks_find(input, "grammar"); grammar; grammar = iks_next_tag(grammar)) { if (!strcmp("grammar", iks_name(grammar))) { const char *error_str = ""; const char *url = iks_find_attrib_soft(grammar, "url"); char *url_dup; char *url_params; if (zstr(url)) { stop_cpa_detectors(component); RAYO_UNLOCK(component); RAYO_DESTROY(component); return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "Missing grammar URL"); } have_grammar = 1; url_dup = strdup(url); if ((url_params = strchr(url_dup, '?'))) { *url_params = '\0'; url_params++; } if (switch_core_hash_find(component->signals, url)) { free(url_dup); stop_cpa_detectors(component); RAYO_UNLOCK(component); RAYO_DESTROY(component); return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "Duplicate URL"); } /* start detector */ /* TODO return better reasons... */ if (rayo_cpa_detector_start(switch_core_session_get_uuid(session), url_dup, &error_str)) { struct cpa_signal *cpa_signal = switch_core_alloc(pool, sizeof(*cpa_signal)); cpa_signal->terminate = !zstr(url_params) && strstr(url_params, "terminate=true"); cpa_signal->name = switch_core_strdup(pool, url_dup); switch_core_hash_insert(component->signals, cpa_signal->name, cpa_signal); subscribe(switch_core_session_get_uuid(session), cpa_signal->name, RAYO_JID(component)); } else { free(url_dup); stop_cpa_detectors(component); RAYO_UNLOCK(component); RAYO_DESTROY(component); return iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, error_str); } free(url_dup); } } if (!have_grammar) { stop_cpa_detectors(component); RAYO_UNLOCK(component); RAYO_DESTROY(component); return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "No grammar defined"); } /* acknowledge command */ rayo_component_send_start(RAYO_COMPONENT(component), iq); /* TODO hangup race condition */ subscribe(switch_core_session_get_uuid(session), "hangup", RAYO_JID(component)); /* ready to forward detector events */ component->ready = 1; return NULL; }