- for incoming calls, go CS_ROUTING only when number is dialed.
CS_HIBERNATE before
- start media when both side have answered
Also:
- send tone for UNALLOCATED_NUMBER and USER_BUSY
- if channel variables are not sufficent to set call info, ask the
partner channel
switch_status_t channel_on_init(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
- private_t *tech_pvt = switch_core_session_get_private(session);
-
- switch_set_flag_locked(tech_pvt, TFLAG_IO);
-
- /* Move channel's state machine to ROUTING. This means the call is trying
- to get from the initial start where the call because, to the point
- where a destination has been identified. If the channel is simply
- left in the initial state, nothing will happen. */
- switch_channel_set_state(channel, CS_ROUTING);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL INIT\n", switch_channel_get_name(channel));
return SWITCH_STATUS_SUCCESS;
}
+struct channel_on_routing_helper {
+ private_t *tech_pvt;
+ listener_t *listener;
+ uint32_t line_instance;
+};
+
+int channel_on_routing_callback(void *pArg, int argc, char **argv, char **columnNames)
+{
+ struct channel_on_routing_helper *helper = pArg;
+ listener_t *listener = NULL;
+
+ char *device_name = argv[0];
+ uint32_t device_instance = atoi(argv[1]);
+ /* uint32_t position = atoi(argv[2]); */
+ uint32_t line_instance = atoi(argv[3]);
+ /* char *label = argv[4]; */
+ /* char *value = argv[5]; */
+ /* char *caller_name = argv[6]; */
+ /* uint32_t ring_on_idle = atoi(argv[7]); */
+ /* uint32_t ring_on_active = atoi(argv[8]); */
+ /* uint32_t busy_trigger = atoi(argv[9]); */
+ /* char *forward_all = argv[10]; */
+ /* char *forward_busy = argv[11]; */
+ /* char *forward_noanswer = argv[12]; */
+ /* uint32_t noanswer_duration = atoi(argv[13]); */
+ /* char *channel_uuid = argv[14]; */
+ /* uint32_t call_id = atoi(argv[15]); */
+ /* uint32_t call_state = atoi(argv[16]); */
+
+ skinny_profile_find_listener_by_device_name_and_instance(helper->tech_pvt->profile, device_name, device_instance, &listener);
+ if(listener) {
+ if(!strcmp(device_name, helper->listener->device_name)
+ && (device_instance == helper->listener->device_instance)
+ && (line_instance == helper->line_instance)) {/* the calling line */
+ helper->tech_pvt->caller_profile->dialplan = switch_core_strdup(helper->tech_pvt->caller_profile->pool, listener->profile->dialplan);
+ helper->tech_pvt->caller_profile->context = switch_core_strdup(helper->tech_pvt->caller_profile->pool, listener->profile->context);
+ send_dialed_number(listener, helper->tech_pvt->caller_profile->destination_number, line_instance, helper->tech_pvt->call_id);
+ skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_PROCEED);
+ skinny_session_send_call_info(helper->tech_pvt->session, listener, line_instance);
+ } else {
+ send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_ON);
+ skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_IN_USE_REMOTELY);
+ send_select_soft_keys(listener, line_instance, helper->tech_pvt->call_id, 10, 0xffff);
+ send_display_prompt_status(listener, 0, SKINNY_DISP_IN_USE_REMOTE,
+ line_instance, helper->tech_pvt->call_id);
+ skinny_session_send_call_info(helper->tech_pvt->session, listener, line_instance);
+ }
+ }
+ return 0;
+}
+
switch_status_t channel_on_routing(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
+ skinny_action_t action;
+ private_t *tech_pvt = switch_core_session_get_private(session);
+ char *data = NULL;
+ listener_t *listener = NULL;
+ struct channel_on_routing_helper helper = {0};
+
+ if(switch_test_flag(tech_pvt, TFLAG_FORCE_ROUTE)) {
+ action = SKINNY_ACTION_ROUTE;
+ switch_clear_flag_locked(tech_pvt, TFLAG_FORCE_ROUTE);
+ } else {
+ action = skinny_session_dest_match_pattern(session, &data);
+ }
+ switch(action) {
+ case SKINNY_ACTION_ROUTE:
+ skinny_profile_find_listener_by_device_name_and_instance(tech_pvt->profile,
+ switch_channel_get_variable(channel, "skinny_device_name"),
+ atoi(switch_channel_get_variable(channel, "skinny_device_instance")), &listener);
+ if (listener) {
+ helper.tech_pvt = tech_pvt;
+ helper.listener = listener;
+ helper.line_instance = atoi(switch_channel_get_variable(channel, "skinny_line_instance"));
+ skinny_session_walk_lines(tech_pvt->profile, switch_core_session_get_uuid(session), channel_on_routing_callback, &helper);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Could not find listener %s:%s for Channel %s\n",
+ switch_channel_get_variable(channel, "skinny_device_name"), switch_channel_get_variable(channel, "skinny_device_instance"),
+ switch_channel_get_name(channel));
+ }
+ break;
+ case SKINNY_ACTION_WAIT:
+ /* for now, wait forever */
+ switch_channel_set_state(channel, CS_HIBERNATE);
+ break;
+ case SKINNY_ACTION_DROP:
+ default:
+ switch_channel_hangup(channel, SWITCH_CAUSE_UNALLOCATED_NUMBER);
+ }
+ }
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL EXECUTE\n", switch_channel_get_name(channel));
-
return SWITCH_STATUS_SUCCESS;
}
send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_OFF);
switch (helper->cause) {
case SWITCH_CAUSE_UNALLOCATED_NUMBER:
+ send_start_tone(listener, SKINNY_TONE_REORDER, 0, line_instance, call_id);
+ skinny_session_send_call_info(helper->tech_pvt->session, listener, line_instance);
send_display_prompt_status(listener, 0, SKINNY_DISP_UNKNOWN_NUMBER, line_instance, call_id);
break;
case SWITCH_CAUSE_USER_BUSY:
+ send_start_tone(listener, SKINNY_TONE_BUSYTONE, 0, line_instance, call_id);
send_display_prompt_status(listener, 0, SKINNY_DISP_BUSY, line_instance, call_id);
- break;
+ break;
case SWITCH_CAUSE_NORMAL_CLEARING:
send_clear_prompt_status(listener, line_instance, call_id);
break;
switch_status_t channel_answer_channel(switch_core_session_t *session)
{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ private_t *tech_pvt = switch_core_session_get_private(session);
+ listener_t *listener = NULL;
+
+ skinny_profile_find_listener_by_device_name_and_instance(tech_pvt->profile,
+ switch_channel_get_variable(channel, "skinny_device_name"),
+ atoi(switch_channel_get_variable(channel, "skinny_device_instance")), &listener);
+ if (listener) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Bli!\n");
+ skinny_session_start_media(session, listener, atoi(switch_channel_get_variable(channel, "skinny_line_instance")));
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Unable to find listener to answer %s:%s\n",
+ switch_channel_get_variable(channel, "skinny_device_name"), switch_channel_get_variable(channel, "skinny_device_instance"));
+ }
return SWITCH_STATUS_SUCCESS;
}
tech_pvt->caller_profile = caller_profile;
switch_channel_set_flag(channel, CF_OUTBOUND);
- switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND);
if ((sql = switch_mprintf(
"INSERT INTO skinny_active_lines "
/*****************************************************************************/
typedef enum {
TFLAG_IO = (1 << 0),
- TFLAG_INBOUND = (1 << 1),
- TFLAG_OUTBOUND = (1 << 2),
TFLAG_DTMF = (1 << 3),
TFLAG_VOICE = (1 << 4),
TFLAG_HANGUP = (1 << 5),
TFLAG_CODEC = (1 << 7),
TFLAG_READING = (1 << 9),
- TFLAG_WRITING = (1 << 10)
+ TFLAG_WRITING = (1 << 10),
+ TFLAG_FORCE_ROUTE = (1 << 11)
} TFLAGS;
typedef enum {
return SWITCH_STATUS_SUCCESS;
}
+switch_status_t skinny_set_channel_variables(switch_channel_t *channel, listener_t *listener, uint32_t line_instance)
+{
+ switch_channel_set_variable(channel, "skinny_profile_name", listener->profile->name);
+ switch_channel_set_variable(channel, "skinny_device_name", listener->device_name);
+ switch_channel_set_variable_printf(channel, "skinny_device_instance", "%d", listener->device_instance);
+ switch_channel_set_variable_printf(channel, "skinny_line_instance", "%d", line_instance);
+ return SWITCH_STATUS_SUCCESS;
+}
+
/*****************************************************************************/
/*****************************************************************************/
switch_status_t skinny_session_walk_lines(skinny_profile_t *profile, char *channel_uuid, switch_core_db_callback_func_t callback, void *data)
ptr = (char *) reply;
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG,
- "Sending %s (type=%x,length=%d).\n",
- skinny_message_type2str(reply->type), reply->type, reply->length);
+ "Sending %s (type=%x,length=%d) to %s:%d.\n",
+ skinny_message_type2str(reply->type), reply->type, reply->length,
+ listener->device_name, listener->device_instance);
switch_socket_send(listener->sock, ptr, &len);
return SWITCH_STATUS_SUCCESS;
switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req);
switch_status_t skinny_device_event(listener_t *listener, switch_event_t **ev, switch_event_types_t event_id, const char *subclass_name);
+switch_status_t skinny_set_channel_variables(switch_channel_t *channel, listener_t *listener, uint32_t line_instance);
switch_status_t skinny_session_walk_lines(skinny_profile_t *profile, char *channel_uuid, switch_core_db_callback_func_t callback, void *data);
snprintf(name, sizeof(name), "SKINNY/%s/%s:%d/%d", listener->profile->name,
listener->device_name, listener->device_instance, *line_instance_p);
switch_channel_set_name(channel, name);
+ skinny_set_channel_variables(channel, listener, *line_instance_p);
if (switch_core_session_thread_launch(nsession) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(nsession), SWITCH_LOG_CRIT,
send_display_prompt_status(listener, 0, "\200\000",
*line_instance_p, tech_pvt->call_id);
send_activate_call_plane(listener, *line_instance_p);
+ if (switch_channel_get_state(channel) == CS_NEW) {
+ switch_channel_set_state(channel, CS_HIBERNATE);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(nsession), SWITCH_LOG_CRIT,
+ "Wow! this channel should be in CS_NEW state, but it is not!\n");
+ }
goto done;
error:
}
-struct skinny_session_process_dest_helper {
- private_t *tech_pvt;
- listener_t *listener;
- uint32_t line_instance;
-};
-
-int skinny_session_process_dest_callback(void *pArg, int argc, char **argv, char **columnNames)
-{
- struct skinny_session_process_dest_helper *helper = pArg;
- listener_t *listener = NULL;
-
- char *device_name = argv[0];
- uint32_t device_instance = atoi(argv[1]);
- /* uint32_t position = atoi(argv[2]); */
- uint32_t line_instance = atoi(argv[3]);
- /* char *label = argv[4]; */
- /* char *value = argv[5]; */
- /* char *caller_name = argv[6]; */
- /* uint32_t ring_on_idle = atoi(argv[7]); */
- /* uint32_t ring_on_active = atoi(argv[8]); */
- /* uint32_t busy_trigger = atoi(argv[9]); */
- /* char *forward_all = argv[10]; */
- /* char *forward_busy = argv[11]; */
- /* char *forward_noanswer = argv[12]; */
- /* uint32_t noanswer_duration = atoi(argv[13]); */
- /* char *channel_uuid = argv[14]; */
- /* uint32_t call_id = atoi(argv[15]); */
- /* uint32_t call_state = atoi(argv[16]); */
-
- skinny_profile_find_listener_by_device_name_and_instance(helper->tech_pvt->profile, device_name, device_instance, &listener);
- if(listener) {
- if(!strcmp(device_name, helper->listener->device_name)
- && (device_instance == helper->listener->device_instance)
- && (line_instance == helper->line_instance)) {/* the calling line */
- /* nothing */
- } else {
- send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_ON);
- skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_IN_USE_REMOTELY);
- send_select_soft_keys(listener, line_instance, helper->tech_pvt->call_id, 10, 0xffff);
- send_display_prompt_status(listener, 0, SKINNY_DISP_IN_USE_REMOTE,
- line_instance, helper->tech_pvt->call_id);
- skinny_session_send_call_info(helper->tech_pvt->session, listener, line_instance);
- }
- }
- return 0;
-}
-
switch_status_t skinny_session_process_dest(switch_core_session_t *session, listener_t *listener, uint32_t line_instance, char *dest, char append_dest, uint32_t backspace)
{
- skinny_action_t action;
switch_channel_t *channel = NULL;
private_t *tech_pvt = NULL;
- char *data = NULL;
- struct skinny_session_process_dest_helper helper = {0};
switch_assert(session);
switch_assert(listener);
} else {
tech_pvt->caller_profile->destination_number = switch_core_strdup(tech_pvt->caller_profile->pool,
dest);
+ switch_set_flag_locked(tech_pvt, TFLAG_FORCE_ROUTE);
}
- if(dest) {
- action = SKINNY_ACTION_ROUTE;
- } else {
- action = skinny_session_dest_match_pattern(session, &data);
- }
- switch(action) {
- case SKINNY_ACTION_ROUTE:
- tech_pvt->caller_profile->dialplan = switch_core_strdup(tech_pvt->caller_profile->pool, listener->profile->dialplan);
- tech_pvt->caller_profile->context = switch_core_strdup(tech_pvt->caller_profile->pool, listener->profile->context);
- send_dialed_number(listener, tech_pvt->caller_profile->destination_number, line_instance, tech_pvt->call_id);
- skinny_line_set_state(listener, line_instance, tech_pvt->call_id, SKINNY_PROCEED);
- skinny_session_send_call_info(session, listener, line_instance);
-
- skinny_session_start_media(session, listener, line_instance);
-
- helper.tech_pvt = tech_pvt;
- helper.listener = listener;
- helper.line_instance = line_instance;
- skinny_session_walk_lines(tech_pvt->profile, switch_core_session_get_uuid(session), skinny_session_process_dest_callback, &helper);
- break;
- case SKINNY_ACTION_WAIT:
- /* for now, wait forever */
- break;
- case SKINNY_ACTION_DROP:
- default:
- switch_channel_hangup(channel, SWITCH_CAUSE_UNALLOCATED_NUMBER);
- }
+
+ switch_channel_set_state(channel, CS_ROUTING);
return SWITCH_STATUS_SUCCESS;
}
/* Calling party */
if (zstr((caller_party_name = switch_channel_get_variable(channel, "effective_caller_id_name"))) &&
- zstr((caller_party_name = switch_channel_get_variable(channel, "caller_id_name")))) {
+ zstr((caller_party_name = switch_channel_get_variable(channel, "caller_id_name"))) &&
+ zstr((caller_party_name = switch_channel_get_variable_partner(channel, "effective_caller_id_name"))) &&
+ zstr((caller_party_name = switch_channel_get_variable_partner(channel, "caller_id_name")))) {
caller_party_name = SWITCH_DEFAULT_CLID_NAME;
}
if (zstr((caller_party_number = switch_channel_get_variable(channel, "effective_caller_id_number"))) &&
- zstr((caller_party_number = switch_channel_get_variable(channel, "caller_id_number")))) {
+ zstr((caller_party_number = switch_channel_get_variable(channel, "caller_id_number"))) &&
+ zstr((caller_party_number = switch_channel_get_variable_partner(channel, "effective_caller_id_number"))) &&
+ zstr((caller_party_number = switch_channel_get_variable_partner(channel, "caller_id_number")))) {
caller_party_number = "0000000000";
}
/* Called party */
if (zstr((called_party_name = switch_channel_get_variable(channel, "effective_callee_id_name"))) &&
- zstr((called_party_name = switch_channel_get_variable(channel, "callee_id_name")))) {
+ zstr((called_party_name = switch_channel_get_variable(channel, "callee_id_name"))) &&
+ zstr((called_party_name = switch_channel_get_variable_partner(channel, "effective_callee_id_name"))) &&
+ zstr((called_party_name = switch_channel_get_variable_partner(channel, "callee_id_name")))) {
called_party_name = SWITCH_DEFAULT_CLID_NAME;
}
if (zstr((called_party_number = switch_channel_get_variable(channel, "effective_callee_id_number"))) &&
zstr((called_party_number = switch_channel_get_variable(channel, "callee_id_number"))) &&
+ zstr((called_party_number = switch_channel_get_variable_partner(channel, "effective_callee_id_number"))) &&
+ zstr((called_party_number = switch_channel_get_variable_partner(channel, "callee_id_number"))) &&
zstr((called_party_number = switch_channel_get_variable(channel, "destination_number")))) {
called_party_number = "0000000000";
}
skinny_session_walk_lines(tech_pvt->profile, switch_core_session_get_uuid(session), skinny_session_answer_callback, &helper);
+ if (switch_channel_get_state(channel) == CS_INIT) {
+ switch_channel_set_state(channel, CS_ROUTING);
+ }
skinny_session_start_media(session, listener, line_instance);
return SWITCH_STATUS_SUCCESS;
channel = switch_core_session_get_channel(session);
tech_pvt = switch_core_session_get_private(session);
+ switch_clear_flag_locked(tech_pvt, TFLAG_IO);
+
send_close_receive_channel(listener,
tech_pvt->call_id, /* uint32_t conference_id, */
tech_pvt->party_id, /* uint32_t pass_thru_party_id, */
0 /* uint32_t g723_bitrate */
);
- if (switch_channel_get_state(channel) == CS_NEW) {
- switch_channel_set_state(channel, CS_INIT);
- }
+ switch_set_flag_locked(tech_pvt, TFLAG_IO);
switch_channel_mark_answered(channel);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
+ "Unable to find session for device %s:%d (call id=%d).\n",
+ listener->device_name, listener->device_instance, request->data.open_receive_channel_ack.pass_thru_party_id);
}
end:
if(session) {
switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *request)
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
- "Received %s (type=%x,length=%d).\n", skinny_message_type2str(request->type), request->type, request->length);
+ "Received %s (type=%x,length=%d) from %s:%d.\n", skinny_message_type2str(request->type), request->type, request->length,
+ listener->device_name, listener->device_instance);
if(zstr(listener->device_name) && request->type != REGISTER_MESSAGE && request->type != ALARM_MESSAGE) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Device should send a register message first.\n");
/* SESSION FUNCTIONS */
switch_status_t skinny_create_ingoing_session(listener_t *listener, uint32_t *line_instance, switch_core_session_t **session);
+skinny_action_t skinny_session_dest_match_pattern(switch_core_session_t *session, char **data);
switch_status_t skinny_session_process_dest(switch_core_session_t *session, listener_t *listener, uint32_t line_instance, char *dest, char append_dest, uint32_t backspace);
switch_status_t skinny_session_send_call_info(switch_core_session_t *session, listener_t *listener, uint32_t line_instance);
switch_call_cause_t skinny_ring_lines(private_t *tech_pvt);