FreeSWITCH API Documentation  1.7.0
switch_core_state_machine.c
Go to the documentation of this file.
1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  * Michael Jerris <mike@jerris.com>
28  * Paul D. Tinsley <pdt at jackhammer.org>
29  *
30  *
31  * switch_core_state_machine.c -- Main Core Library (state machine)
32  *
33  */
34 
35 #include <switch.h>
37 
39 {
41 
44  } else {
47  } else {
49  }
50  }
51 
53 }
54 
56 {
57  switch_caller_extension_t *extension;
58  int rec;
59 
60  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard HANGUP, cause: %s\n",
62 
63  if (switch_true(switch_channel_get_variable(session->channel, "log_audio_stats_on_hangup"))) {
64  switch_rtp_stats_t *audio_stats = NULL;
65 
68  if (audio_stats) {
71  "%s Call statistics:\n"
72  "in_raw_bytes: %d\n"
73  "in_media_bytes: %d\n"
74  "in_packet_count: %d\n"
75  "in_media_packet_count: %d\n"
76  "in_skip_packet_count: %d\n"
77  "in_jitter_packet_count: %d\n"
78  "in_dtmf_packet_count: %d\n"
79  "in_cng_packet_count: %d\n"
80  "in_flush_packet_count: %d\n"
81  "in_largest_jb_size: %d\n\n"
82  "in_jitter_min_variance: %lf\n"
83  "in_jitter_max_variance: %lf\n"
84  "in_jitter_loss_rate: %lf\n"
85  "in_jitter_burst_rate: %lf\n"
86  "in_mean_interval: %lf\n\n"
87  "in_flaw_total: %d\n"
88  "in_quality_percentage: %lf\n"
89  "in_mos: %lf\n\n"
90  "out_raw_bytes: %d\n"
91  "out_media_bytes: %d\n"
92  "out_packet_count: %d\n"
93  "out_media_packet_count: %d\n"
94  "out_skip_packet_count: %d\n"
95  "out_dtmf_packet_count: %d\n"
96  "out_cng_packet_count: %d\n\n"
97  "rtcp_packet_count: %d\n"
98  "rtcp_octet_count: %d\n",
100  (int)audio_stats->inbound.raw_bytes,
101  (int)audio_stats->inbound.media_bytes,
102  (int)audio_stats->inbound.packet_count,
103  (int)audio_stats->inbound.media_packet_count,
104  (int)audio_stats->inbound.skip_packet_count,
105  (int)audio_stats->inbound.jb_packet_count,
106  (int)audio_stats->inbound.dtmf_packet_count,
107  (int)audio_stats->inbound.cng_packet_count,
108  (int)audio_stats->inbound.flush_packet_count,
109  (int)audio_stats->inbound.largest_jb_size,
110  audio_stats->inbound.min_variance,
111  audio_stats->inbound.max_variance,
112  audio_stats->inbound.lossrate,
113  audio_stats->inbound.burstrate,
114  audio_stats->inbound.mean_interval,
115  (int)audio_stats->inbound.flaws,
116  audio_stats->inbound.R,
117  audio_stats->inbound.mos,
118  (int)audio_stats->outbound.raw_bytes,
119  (int)audio_stats->outbound.media_bytes,
120  (int)audio_stats->outbound.packet_count,
121  (int)audio_stats->outbound.media_packet_count,
122  (int)audio_stats->outbound.skip_packet_count,
123  (int)audio_stats->outbound.dtmf_packet_count,
124  (int)audio_stats->outbound.cng_packet_count,
125  (int)audio_stats->rtcp.packet_count,
126  (int)audio_stats->rtcp.octet_count
127  );
128  } else {
129  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s Missing call statistics!\n",
130  switch_channel_get_name(session->channel));
131  }
132  }
133 
136 
137  if (!rec) {
139  }
140 
141 
143  return;
144  }
145 
146  if ((extension = switch_channel_get_caller_extension(session->channel)) == 0) {
147  return;
148  }
149 
150  while(extension->current_application) {
151  switch_caller_application_t *current_application = extension->current_application;
152  switch_status_t status;
153 
154  extension->current_application = extension->current_application->next;
155 
157  current_application->application_name, current_application->application_data);
158 
159 
160  if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_IGNORE) {
161  return;
162  }
163  }
164 
165 
166 
167 
168 
169 }
170 
172 {
173 
174  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard REPORTING, cause: %s\n",
176 }
177 
179 {
180 
182 }
183 
185 {
186  switch_channel_set_variable(session->channel, "call_uuid", switch_core_session_get_uuid(session));
187 
189 
191  switch_core_session_t *other_session = NULL;
192  const char *uuid = switch_core_session_get_uuid(session);
193 
195  const char *other_uuid = switch_channel_get_partner_uuid(session->channel);
196  int x = 0;
197 
198  if (other_uuid) {
199  for (x = 0; other_session == NULL && x < 20; x++) {
200  if (!switch_channel_up(session->channel)) {
201  break;
202  }
203  other_session = switch_core_session_locate(other_uuid);
204  switch_yield(100000);
205  }
206  }
207 
208  if (other_session) {
209  switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
211  switch_channel_wait_for_state_timeout(other_channel, CS_RESET, 5000);
212  switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 2000, NULL);
213 
215  switch_ivr_signal_bridge(session, other_session);
216  } else {
217  switch_ivr_uuid_bridge(uuid, other_uuid);
218  }
219  switch_core_session_rwunlock(other_session);
220  }
221  }
222 
224  }
225 
226 }
227 
229 {
230  switch_dialplan_interface_t *dialplan_interface = NULL;
231  switch_caller_profile_t *caller_profile;
232  switch_caller_extension_t *extension = NULL;
233  char *expanded = NULL;
234  char *dpstr = NULL;
235 
237 
238  switch_channel_set_variable(session->channel, "call_uuid", switch_core_session_get_uuid(session));
239 
240  if ((switch_channel_test_flag(session->channel, CF_ANSWERED) ||
244  }
245 
246  if ((caller_profile = switch_channel_get_caller_profile(session->channel)) == 0) {
247  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't get profile!\n");
249  return;
250  } else {
251  char *dp[25];
252  int argc, x, count = 0;
253 
254  if ((extension = switch_channel_get_queued_extension(session->channel))) {
255  switch_channel_set_caller_extension(session->channel, extension);
257  goto end;
258  }
259 
260  if (!zstr(caller_profile->dialplan)) {
261  if ((dpstr = switch_core_session_strdup(session, caller_profile->dialplan))) {
262  expanded = switch_channel_expand_variables(session->channel, dpstr);
263  argc = switch_separate_string(expanded, ',', dp, (sizeof(dp) / sizeof(dp[0])));
264  for (x = 0; x < argc; x++) {
265  char *dpname = dp[x];
266  char *dparg = NULL;
267 
268  if (dpname) {
269  if ((dparg = strchr(dpname, ':'))) {
270  *dparg++ = '\0';
271  }
272  } else {
273  continue;
274  }
275  if (!(dialplan_interface = switch_loadable_module_get_dialplan_interface(dpname))) {
276  continue;
277  }
278 
279  count++;
280 
281  extension = dialplan_interface->hunt_function(session, dparg, NULL);
282  UNPROTECT_INTERFACE(dialplan_interface);
283 
284  if (extension) {
285  switch_channel_set_caller_extension(session->channel, extension);
287  goto end;
288  }
289  }
290  }
291  }
292 
293  if (!count) {
297  "No Dialplan on answered channel, changing state to HANGUP\n");
299  } else {
300  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No Dialplan, changing state to CONSUME_MEDIA\n");
302  }
303  goto end;
304  }
305  }
306  }
307 
308  if (!extension) {
309 
311  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "No Route, Aborting\n");
313  }
314  }
315 
316  end:
317 
318  if (expanded && dpstr && expanded != dpstr) {
319  free(expanded);
320  }
321 }
322 
324 {
325  switch_caller_extension_t *extension;
326  const char *uuid;
327 
329 
331 
332  switch_channel_set_variable(session->channel, "call_uuid", switch_core_session_get_uuid(session));
333 
334  if (switch_channel_get_variable(session->channel, "recovered") && !switch_channel_test_flag(session->channel, CF_RECOVERED)) {
336  }
337 
338  top:
340 
342 
343  if ((extension = switch_channel_get_caller_extension(session->channel)) == 0) {
345  return;
346  }
347 
348  while (switch_channel_get_state(session->channel) == CS_EXECUTE && extension->current_application) {
349  switch_caller_application_t *current_application = extension->current_application;
350 
351  extension->current_application = extension->current_application->next;
352 
354  current_application->application_name,
355  current_application->application_data) != SWITCH_STATUS_SUCCESS) {
356  return;
357  }
358 
359  if (switch_channel_test_flag(session->channel, CF_RESET)) {
360  goto top;
361  }
362 
363  }
364 
367  (uuid = switch_channel_get_variable(session->channel, "blind_transfer_uuid"))) {
368  switch_core_session_t *other_session;
369 
370  if ((other_session = switch_core_session_locate(uuid))) {
371  switch_core_session_message_t msg = { 0 };
373  msg.from = __FILE__;
374  msg.numeric_arg = 0;
375  switch_core_session_receive_message(other_session, &msg);
376  switch_core_session_rwunlock(other_session);
377 
378  switch_channel_set_variable(session->channel, "park_timeout", "10:blind_transfer");
381  }
382  }
383 
385  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "%s has executed the last dialplan instruction, hanging up.\n",
386  switch_channel_get_name(session->channel));
388  }
389 }
390 
392 {
393 
394  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard EXCHANGE_MEDIA\n", switch_channel_get_name(session->channel));
395 }
396 
398 {
399  switch_assert(session != NULL);
400  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard SOFT_EXECUTE\n", switch_channel_get_name(session->channel));
401 }
402 
404 {
405  switch_assert(session != NULL);
408  switch_ivr_park(session, NULL);
409 }
410 
412 {
413  switch_assert(session != NULL);
414  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard CONSUME_MEDIA\n", switch_channel_get_name(session->channel));
415 }
416 
418 {
419  switch_assert(session != NULL);
420  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard HIBERNATE\n", switch_channel_get_name(session->channel));
421 }
422 
424 {
425  return;
426 }
427 
428 #define STATE_MACRO(__STATE, __STATE_STR) do { \
429  midstate = state; \
430  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "(%s) State %s\n", switch_channel_get_name(session->channel), __STATE_STR); \
431  if (state < CS_HANGUP && switch_channel_get_callstate(session->channel) == CCS_UNHELD) { \
432  switch_channel_set_callstate(session->channel, CCS_ACTIVE); \
433  } \
434  switch_core_session_request_video_refresh(session); \
435  switch_core_media_gen_key_frame(session); \
436  if (!driver_state_handler->on_##__STATE || (driver_state_handler->on_##__STATE(session) == SWITCH_STATUS_SUCCESS \
437  )) { \
438  while (do_extra_handlers && (application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) { \
439  if (!application_state_handler || !application_state_handler->on_##__STATE \
440  || (application_state_handler->on_##__STATE \
441  && application_state_handler->on_##__STATE(session) == SWITCH_STATUS_SUCCESS \
442  )) { \
443  proceed++; \
444  continue; \
445  } else { \
446  proceed = 0; \
447  break; \
448  } \
449  } \
450  index = 0; \
451  if (!proceed) global_proceed = 0; \
452  proceed = 1; \
453  while (do_extra_handlers && proceed && (application_state_handler = switch_core_get_state_handler(index++)) != 0) { \
454  if (!application_state_handler || !application_state_handler->on_##__STATE || \
455  (application_state_handler->on_##__STATE && \
456  application_state_handler->on_##__STATE(session) == SWITCH_STATUS_SUCCESS \
457  )) { \
458  proceed++; \
459  continue; \
460  } else { \
461  proceed = 0; \
462  break; \
463  } \
464  } \
465  if (!proceed || midstate != switch_channel_get_state(session->channel)) global_proceed = 0; \
466  if (global_proceed) { \
467  switch_core_standard_on_##__STATE(session); \
468  } \
469  } \
470  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "(%s) State %s going to sleep\n", switch_channel_get_name(session->channel), __STATE_STR); \
471  } while (silly)
472 
473 
475 {
477 
478  if (state == CS_ROUTING || state == CS_HANGUP) {
480  switch_channel_presence(session->channel, "unknown", "cancelled", NULL);
481  switch_channel_set_variable(session->channel, "presence_call_info", NULL);
482  } else {
483  switch_channel_presence(session->channel, "unknown", switch_channel_state_name(state), NULL);
484  }
485  }
486 }
487 
488 
489 
491 {
492  switch_channel_state_t state = CS_NEW, midstate = CS_DESTROY, endstate;
493  const switch_endpoint_interface_t *endpoint_interface;
494  const switch_state_handler_table_t *driver_state_handler = NULL;
495  const switch_state_handler_table_t *application_state_handler = NULL;
496  int silly = 0;
497  uint32_t new_loops = 500;
498 
499  /*
500  Life of the channel. you have channel and pool in your session
501  everywhere you go you use the session to malloc with
502  switch_core_session_alloc(session, <size>)
503 
504  The endpoint module gets the first crack at implementing the state
505  if it wants to, it can cancel the default behavior by returning SWITCH_STATUS_FALSE
506 
507  Next comes the channel's event handler table that can be set by an application
508  which also can veto the next behavior in line by returning SWITCH_STATUS_FALSE
509 
510  Finally the default state behavior is called.
511 
512 
513  */
514  switch_assert(session != NULL);
515 
517  endpoint_interface = session->endpoint_interface;
518  switch_assert(endpoint_interface != NULL);
519 
520  driver_state_handler = endpoint_interface->state_handler;
521  switch_assert(driver_state_handler != NULL);
522 
523  switch_mutex_lock(session->mutex);
524 
525  while ((state = switch_channel_get_state(session->channel)) != CS_DESTROY) {
526 
527  if (switch_channel_test_flag(session->channel, CF_BLOCK_STATE)) {
528  switch_channel_wait_for_flag(session->channel, CF_BLOCK_STATE, SWITCH_FALSE, 0, NULL);
529  if ((state = switch_channel_get_state(session->channel)) == CS_DESTROY) {
530  break;
531  }
532  }
533 
534  midstate = state;
535  if (state != switch_channel_get_running_state(session->channel) || state >= CS_HANGUP) {
536  int index = 0;
537  int proceed = 1;
538  int global_proceed = 1;
539  int do_extra_handlers = 1;
542 
543  switch_channel_set_running_state(session->channel, state);
544  switch_channel_clear_flag(session->channel, CF_TRANSFER);
545  switch_channel_clear_flag(session->channel, CF_REDIRECT);
547 
548  if (session->endpoint_interface->io_routines->state_run) {
549  rstatus = session->endpoint_interface->io_routines->state_run(session);
550  }
551 
552  if (rstatus == SWITCH_STATUS_SUCCESS) {
553  for (ptr = session->event_hooks.state_run; ptr; ptr = ptr->next) {
554  if ((rstatus = ptr->state_run(session)) != SWITCH_STATUS_SUCCESS) {
555  break;
556  }
557  }
558  }
559 
560  switch (state) {
561  case CS_NEW: /* Just created, Waiting for first instructions */
562  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "(%s) State NEW\n", switch_channel_get_name(session->channel));
563  break;
564  case CS_DESTROY:
565  goto done;
566  case CS_REPORTING: /* Call Detail */
567  {
569  switch_channel_set_state(session->channel, CS_DESTROY);
570  }
571  goto done;
572  case CS_HANGUP: /* Deactivate and end the thread */
573  {
575  if (switch_channel_test_flag(session->channel, CF_VIDEO)) {
577  }
578  switch_channel_set_state(session->channel, CS_REPORTING);
579  }
580 
581  break;
582  case CS_INIT: /* Basic setup tasks */
583  {
585 
586  STATE_MACRO(init, "INIT");
587 
589  switch_channel_event_set_data(session->channel, event);
590  switch_event_fire(&event);
591  }
592 
593  if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
595  switch_channel_event_set_data(session->channel, event);
596  switch_event_fire(&event);
597  }
598  }
599  }
600  break;
601  case CS_ROUTING: /* Look for a dialplan and find something to do */
602  STATE_MACRO(routing, "ROUTING");
603  break;
604  case CS_RESET: /* Reset */
605  STATE_MACRO(reset, "RESET");
606  break;
607  /* These other states are intended for prolonged durations so we do not signal lock for them */
608  case CS_EXECUTE: /* Execute an Operation */
609  STATE_MACRO(execute, "EXECUTE");
610  break;
611  case CS_EXCHANGE_MEDIA: /* loop all data back to source */
612  STATE_MACRO(exchange_media, "EXCHANGE_MEDIA");
613  break;
614  case CS_SOFT_EXECUTE: /* send/recieve data to/from another channel */
615  STATE_MACRO(soft_execute, "SOFT_EXECUTE");
616  break;
617  case CS_PARK: /* wait in limbo */
618  STATE_MACRO(park, "PARK");
619  break;
620  case CS_CONSUME_MEDIA: /* wait in limbo */
621  STATE_MACRO(consume_media, "CONSUME_MEDIA");
622  break;
623  case CS_HIBERNATE: /* sleep */
624  STATE_MACRO(hibernate, "HIBERNATE");
625  break;
626  case CS_NONE:
627  abort();
628  break;
629  }
630 
631  check_presence(session);
632 
633  if (midstate == CS_DESTROY) {
634  break;
635  }
636 
637  }
638 
639  endstate = switch_channel_get_state(session->channel);
640 
641  if (endstate == switch_channel_get_running_state(session->channel)) {
642  if (endstate == CS_NEW) {
643  switch_yield(20000);
645  if (!--new_loops) {
646  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s %s Abandoned\n",
647  session->uuid_str, switch_core_session_get_name(session));
648  switch_channel_set_flag(session->channel, CF_NO_CDR);
650  }
651  } else {
654 
655  if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) {
656  switch_channel_state_thread_lock(session->channel);
657  switch_channel_set_flag(session->channel, CF_THREAD_SLEEPING);
658  if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) {
660  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s session thread sleep state: %s!\n",
661  switch_channel_get_name(session->channel),
663  switch_thread_cond_wait(session->cond, session->mutex);
664  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s session thread wake state: %s!\n",
665  switch_channel_get_name(session->channel),
667 
668 
669  }
671  switch_channel_state_thread_unlock(session->channel);
672  }
673 
676  }
677  }
678  }
679  done:
680  switch_mutex_unlock(session->mutex);
681 
683 }
684 
686 {
688  const switch_endpoint_interface_t *endpoint_interface;
689  const switch_state_handler_table_t *driver_state_handler = NULL;
690  const switch_state_handler_table_t *application_state_handler = NULL;
691  int proceed = 1;
692  int global_proceed = 1;
693  int do_extra_handlers = 1;
694  int silly = 0;
695  int index = 0;
696 
697  switch_channel_set_callstate(session->channel, CCS_DOWN);
698 
699  switch_assert(session != NULL);
700  switch_channel_set_running_state(session->channel, CS_DESTROY);
701  switch_channel_clear_flag(session->channel, CF_TRANSFER);
702  switch_channel_clear_flag(session->channel, CF_REDIRECT);
703 
704  endpoint_interface = session->endpoint_interface;
705  switch_assert(endpoint_interface != NULL);
706 
707  driver_state_handler = endpoint_interface->state_handler;
708  switch_assert(driver_state_handler != NULL);
709 
710  STATE_MACRO(destroy, "DESTROY");
711 
712  switch_channel_clear_device_record(session->channel);
713 
714  return;
715 }
716 
717 static void api_hook(switch_core_session_t *session, const char *hook_var, int use_session)
718 {
719  if (!zstr(hook_var)) {
720  switch_stream_handle_t stream = { 0 };
721  char *cmd = strdup(hook_var);
722  char *arg = NULL;
723  char *expanded = NULL;
724 
725  if ((arg = strchr(cmd, ':')) && *(arg + 1) == ':') {
726  *arg++ = '\0';
727  *arg++ = '\0';
728  } else {
729  if ((arg = strchr(cmd, ' '))) {
730  *arg++ = '\0';
731  }
732  }
733 
734  SWITCH_STANDARD_STREAM(stream);
735 
738  expanded = switch_event_expand_headers(stream.param_event, arg);
739 
740  switch_api_execute(cmd, expanded, use_session ? session : NULL, &stream);
741 
742  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Hangup Command %s %s(%s):\n%s\n",
743  use_session ? "with Session" : "with no Session", cmd, switch_str_nil(expanded),
744  switch_str_nil((char *) stream.data) );
745 
746  if (expanded != arg) {
747  switch_safe_free(expanded);
748  }
749 
750  switch_safe_free(cmd);
751 
752  switch_safe_free(stream.data);
753  }
754 }
755 
756 
757 
759 {
760  switch_call_cause_t cause = switch_channel_get_cause(session->channel);
761  switch_call_cause_t cause_q850 = switch_channel_get_cause_q850(session->channel);
762  int proceed = 1;
763  int global_proceed = 1;
764  int do_extra_handlers = 1;
765  int silly = 0;
766  int index = 0;
767  switch_channel_state_t state = switch_channel_get_state(session->channel), midstate = state;
768  const switch_endpoint_interface_t *endpoint_interface;
769  const switch_state_handler_table_t *driver_state_handler = NULL;
770  const switch_state_handler_table_t *application_state_handler = NULL;
771  const char *hook_var;
772  int use_session = 0;
773 
774  if (!force) {
776  return;
777  }
778 
779  if (switch_thread_self() != session->thread_id) {
780  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10, "%s thread mismatch skipping state handler.\n",
781  switch_channel_get_name(session->channel));
782  return;
783  }
784  }
785 
786  if (switch_test_flag(session, SSF_HANGUP)) {
787  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10, "%s handler already called, skipping state handler.\n",
788  switch_channel_get_name(session->channel));
789  return;
790  }
791 
792  endpoint_interface = session->endpoint_interface;
793  switch_assert(endpoint_interface != NULL);
794 
795  driver_state_handler = endpoint_interface->state_handler;
796  switch_assert(driver_state_handler != NULL);
797 
798  switch_channel_set_hangup_time(session->channel);
799 
801 
802  switch_channel_stop_broadcast(session->channel);
803 
804  switch_channel_set_variable(session->channel, "hangup_cause", switch_channel_cause2str(cause));
805  switch_channel_set_variable_printf(session->channel, "hangup_cause_q850", "%d", cause_q850);
806  //switch_channel_presence(session->channel, "unknown", switch_channel_cause2str(cause), NULL);
807 
808  switch_channel_set_timestamps(session->channel);
809  switch_channel_set_callstate(session->channel, CCS_HANGUP);
810 
811  STATE_MACRO(hangup, "HANGUP");
812 
814 
815  if ((hook_var = switch_channel_get_variable(session->channel, SWITCH_API_HANGUP_HOOK_VARIABLE))) {
816 
818  use_session = 1;
819  }
820 
821  api_hook(session, hook_var, use_session);
822  }
823 
824  switch_channel_process_device_hangup(session->channel);
825 
826  switch_set_flag(session, SSF_HANGUP);
827 
828 }
829 
831 {
832  switch_channel_state_t state = switch_channel_get_state(session->channel), midstate = state;
833  const switch_endpoint_interface_t *endpoint_interface;
834  const switch_state_handler_table_t *driver_state_handler = NULL;
835  const switch_state_handler_table_t *application_state_handler = NULL;
836  int proceed = 1;
837  int global_proceed = 1;
838  int do_extra_handlers = 1;
839  int silly = 0;
840  int index = 0;
841  const char *var = switch_channel_get_variable(session->channel, SWITCH_PROCESS_CDR_VARIABLE);
842  const char *skip_var = switch_channel_get_variable(session->channel, SWITCH_SKIP_CDR_CAUSES_VARIABLE);
843  const char *hook_var;
844  int use_session = 0;
846  switch_call_cause_t cause = switch_channel_get_cause(session->channel);
847 
848  if (switch_channel_test_flag(session->channel, CF_REPORTING)) {
849  return;
850  }
851 
852  switch_channel_set_flag(session->channel, CF_REPORTING);
853 
854  switch_assert(session != NULL);
855 
856  endpoint_interface = session->endpoint_interface;
857  switch_assert(endpoint_interface != NULL);
858 
859  driver_state_handler = endpoint_interface->state_handler;
860  switch_assert(driver_state_handler != NULL);
861 
862  if (!zstr(var)) {
863  if (!strcasecmp(var, "a_only")) {
864  if (switch_channel_get_originator_caller_profile(session->channel)) {
865  do_extra_handlers = 0;
866  }
867  } else if (!strcasecmp(var, "b_only")) {
868  if (switch_channel_get_originatee_caller_profile(session->channel)) {
869  do_extra_handlers = 0;
870  }
871  } else if (!switch_true(var)) {
872  do_extra_handlers = 0;
873  }
874  }
875 
876 
877  if (!zstr(skip_var)) {
878  int x, ttl = 0;
879  char *list[128] = { 0 };
880  char *dup = switch_core_session_strdup(session, skip_var);
881 
882  ttl = switch_split(dup, '|', list);
883 
884  for(x = 0; x < ttl; x++) {
885  if (switch_channel_str2cause(list[x]) == cause) {
886  do_extra_handlers = 0;
887  break;
888  }
889  }
890  }
891 
892  if (switch_channel_test_flag(session->channel, CF_NO_CDR)) {
893  do_extra_handlers = 0;
894  }
895 
896 
897  STATE_MACRO(reporting, "REPORTING");
898 
899  if ((hook_var = switch_channel_get_variable(session->channel, SWITCH_API_REPORTING_HOOK_VARIABLE))) {
900 
902  use_session = 1;
903  }
904 
905  api_hook(session, hook_var, use_session);
906  }
907 
910  switch_channel_event_set_data(session->channel, event);
911  if (switch_true(switch_channel_get_variable(session->channel, "hangup_complete_with_xml"))) {
912  switch_xml_t cdr = NULL;
913  char *xml_cdr_text;
914 
915  if (switch_ivr_generate_xml_cdr(session, &cdr) == SWITCH_STATUS_SUCCESS) {
916  xml_cdr_text = switch_xml_toxml(cdr, SWITCH_FALSE);
917  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CDR-Attached", "xml");
918  switch_event_add_body(event, "%s", xml_cdr_text);
919  switch_xml_free(cdr);
920  switch_safe_free(xml_cdr_text);
921  }
922  }
923  switch_event_fire(&event);
924  }
925 
926 
927 
928  return;
929 }
930 
931 /* For Emacs:
932  * Local Variables:
933  * mode:c
934  * indent-tabs-mode:t
935  * tab-width:4
936  * c-basic-offset:4
937  * End:
938  * For VIM:
939  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
940  */
switch_status_t switch_channel_set_variable_printf(switch_channel_t *channel, const char *varname, const char *fmt,...)
void switch_core_session_hangup_state(switch_core_session_t *session, switch_bool_t force)
switch_channel_state_t switch_channel_get_state(switch_channel_t *channel)
Get the current state of a channel in the state engine.
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:412
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it's state machine to end.
void switch_xml_free(_In_opt_ switch_xml_t xml)
frees the memory allocated for an switch_xml structure
switch_size_t flaws
Definition: switch_types.h:657
switch_caller_extension_t * switch_channel_get_caller_extension(switch_channel_t *channel)
Retrieve caller extension from a given channel.
#define SWITCH_CHANNEL_SESSION_LOG(x)
#define switch_event_expand_headers(_event, _in)
Definition: switch_event.h:354
An Abstract Representation of a dialplan extension.
void switch_core_session_reporting_state(switch_core_session_t *session)
Call Specific Data.
Definition: switch_caller.h:73
char * switch_xml_toxml(_In_ switch_xml_t xml, _In_ switch_bool_t prn_header)
Converts an switch_xml structure back to xml in html format. Returns a string of html data that \ mus...
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:631
switch_rtp_numbers_t inbound
Definition: switch_types.h:690
switch_rtp_stats_t * switch_core_media_get_stats(switch_core_session_t *session, switch_media_type_t type, switch_memory_pool_t *pool)
switch_status_t switch_channel_set_timestamps(_In_ switch_channel_t *channel)
switch_core_session_message_types_t message_id
Definition: switch_core.h:181
void switch_core_session_reset(_In_ switch_core_session_t *session, switch_bool_t flush_dtmf, switch_bool_t reset_read_codec)
Reset the buffers and resampler on a session.
void switch_channel_set_hangup_time(switch_channel_t *channel)
Abstraction of an module endpoint interface This is the glue between the abstract idea of a "channel"...
const char * switch_channel_get_partner_uuid(switch_channel_t *channel)
#define switch_channel_set_state(channel, state)
Set the current state of a channel.
const char * switch_channel_cause2str(_In_ switch_call_cause_t cause)
return a cause string for a given cause
static void switch_core_standard_on_hibernate(switch_core_session_t *session)
#define switch_channel_stop_broadcast(_channel)
#define switch_channel_up(_channel)
void switch_channel_state_thread_lock(switch_channel_t *channel)
void switch_channel_event_set_data(_In_ switch_channel_t *channel, _In_ switch_event_t *event)
Add information about a given channel to an event object.
switch_bool_t
Definition: switch_types.h:405
#define switch_channel_presence(_a, _b, _c, _d)
static void switch_core_standard_on_destroy(switch_core_session_t *session)
switch_size_t largest_jb_size
Definition: switch_types.h:637
#define switch_split(_data, _delim, _array)
Definition: switch_utils.h:342
static void check_presence(switch_core_session_t *session)
switch_status_t switch_api_execute(const char *cmd, const char *arg, switch_core_session_t *session, switch_stream_handle_t *stream)
Execute a registered API command.
switch_memory_pool_t * pool
Representation of an event.
Definition: switch_event.h:80
#define switch_channel_ready(_channel)
switch_status_t switch_event_add_body(switch_event_t *event, const char *fmt,...) PRINTF_FUNCTION(2
Add a body to an event.
An Abstract Representation of a dialplan Application.
static void switch_core_standard_on_execute(switch_core_session_t *session)
switch_status_t switch_ivr_park(switch_core_session_t *session, switch_input_args_t *args)
Definition: switch_ivr.c:892
switch_channel_state_t switch_channel_get_running_state(switch_channel_t *channel)
A representation of an XML tree.
Definition: switch_xml.h:76
void switch_channel_clear_device_record(switch_channel_t *channel)
Abstract interface to a dialplan module.
switch_status_t switch_thread_cond_wait(switch_thread_cond_t *cond, switch_mutex_t *mutex)
Definition: switch_apr.c:355
const char * switch_channel_state_name(_In_ switch_channel_state_t state)
Render the name of the provided state enum.
#define switch_core_session_get_name(_s)
Definition: switch_core.h:271
static void switch_core_standard_on_exchange_media(switch_core_session_t *session)
switch_size_t media_bytes
Definition: switch_types.h:628
const char * dialplan
Definition: switch_caller.h:77
switch_status_t switch_ivr_parse_all_events(switch_core_session_t *session)
Parse all commands from an event.
Definition: switch_ivr.c:867
void switch_channel_process_device_hangup(switch_channel_t *channel)
switch_status_t switch_ivr_media(const char *uuid, switch_media_flag_t flags)
Signal a session to request direct media access to it's remote end.
Definition: switch_ivr.c:1674
switch_size_t dtmf_packet_count
Definition: switch_types.h:634
struct switch_runtime runtime
Definition: switch_core.c:64
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
struct switch_io_event_hook_state_run * next
#define SWITCH_SKIP_CDR_CAUSES_VARIABLE
Definition: switch_types.h:178
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:177
#define zstr(x)
Definition: switch_utils.h:281
switch_caller_profile_t * switch_channel_get_originatee_caller_profile(switch_channel_t *channel)
Retrieve the given channel's originatee caller profile.
struct switch_caller_application * next
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:290
#define switch_core_session_execute_application(_a, _b, _c)
Execute an application on a session.
Definition: switch_core.h:1103
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define UNPROTECT_INTERFACE(_it)
switch_state_handler_table_t * state_handler
#define switch_clear_flag(obj, flag)
Clear a flag on an arbitrary object while locked.
Definition: switch_utils.h:655
switch_status_t switch_ivr_blind_transfer_ack(switch_core_session_t *session, switch_bool_t success)
Definition: switch_ivr.c:4254
static void switch_core_standard_on_consume_media(switch_core_session_t *session)
switch_rtcp_numbers_t rtcp
Definition: switch_types.h:692
#define SWITCH_PROCESS_CDR_VARIABLE
Definition: switch_types.h:177
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
unsigned int switch_separate_string(_In_ char *buf, char delim, _Post_count_(return) char **array, unsigned int arraylen)
Separate a string into an array based on a character delimiter.
switch_channel_t * channel
static void switch_core_standard_on_init(switch_core_session_t *session)
switch_size_t raw_bytes
Definition: switch_types.h:627
switch_dialplan_hunt_function_t hunt_function
void switch_core_recovery_untrack(switch_core_session_t *session, switch_bool_t force)
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:285
#define SWITCH_API_REPORTING_HOOK_VARIABLE
Definition: switch_types.h:175
#define switch_channel_get_variable(_c, _v)
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
#define switch_channel_set_running_state(channel, state)
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
switch_rtp_numbers_t outbound
Definition: switch_types.h:691
switch_status_t switch_ivr_uuid_bridge(const char *originator_uuid, const char *originatee_uuid)
Bridge two existing sessions.
switch_status_t switch_channel_get_variables(switch_channel_t *channel, switch_event_t **event)
#define SWITCH_SESSION_IN_HANGUP_HOOK_VARIABLE
Definition: switch_types.h:176
Node in which to store state run callback hooks.
static void switch_core_standard_on_park(switch_core_session_t *session)
switch_call_cause_t switch_channel_str2cause(_In_ const char *str)
return a cause code for a given string
void switch_channel_set_caller_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension)
Assign a caller extension to a given channel.
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH+1]
#define SWITCH_STANDARD_STREAM(s)
void switch_channel_wait_for_state_timeout(switch_channel_t *other_channel, switch_channel_state_t want_state, uint32_t timeout)
switch_size_t packet_count
Definition: switch_types.h:629
switch_call_cause_t
switch_caller_application_t * current_application
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1217
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
void switch_core_session_video_reset(switch_core_session_t *session)
char * switch_core_session_get_uuid(_In_ switch_core_session_t *session)
Retrieve the unique identifier from a session.
switch_size_t jb_packet_count
Definition: switch_types.h:633
static void switch_core_standard_on_soft_execute(switch_core_session_t *session)
switch_size_t skip_packet_count
Definition: switch_types.h:632
void switch_core_media_set_stats(switch_core_session_t *session)
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:903
static void switch_core_standard_on_reset(switch_core_session_t *session)
switch_caller_extension_t * switch_channel_get_queued_extension(switch_channel_t *channel)
static void switch_core_standard_on_reporting(switch_core_session_t *session)
switch_channel_state_t
Channel States (these are the defaults, CS_SOFT_EXECUTE, CS_EXCHANGE_MEDIA, and CS_CONSUME_MEDIA are ...
#define switch_channel_expand_variables(_channel, _in)
void switch_core_session_run(switch_core_session_t *session)
#define switch_channel_set_callstate(channel, state)
switch_status_t
Common return values.
void switch_core_session_wake_video_thread(switch_core_session_t *session)
switch_dialplan_interface_t * switch_loadable_module_get_dialplan_interface(const char *name)
Retrieve the dialplan interface by it's registered name.
#define switch_core_session_locate(uuid_str)
Locate a session based on it's uuid.
Definition: switch_core.h:916
Main Library Header.
#define switch_core_media_bug_remove_all(_s)
Definition: switch_core.h:404
switch_call_cause_t switch_channel_get_cause_q850(switch_channel_t *channel)
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:383
switch_size_t flush_packet_count
Definition: switch_types.h:636
#define SWITCH_DECLARE(type)
#define switch_channel_set_flag(_c, _f)
switch_size_t media_packet_count
Definition: switch_types.h:631
switch_call_direction_t switch_channel_direction(switch_channel_t *channel)
static void switch_core_standard_on_hangup(switch_core_session_t *session)
static void switch_core_standard_on_routing(switch_core_session_t *session)
static void api_hook(switch_core_session_t *session, const char *hook_var, int use_session)
struct apr_pool_t switch_memory_pool_t
#define STATE_MACRO(__STATE, __STATE_STR)
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:624
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session's pool.
Definition: switch_core.h:717
switch_thread_id_t switch_thread_self(void)
Definition: switch_apr.c:79
void switch_channel_state_thread_unlock(switch_channel_t *channel)
switch_status_t switch_channel_wait_for_flag(switch_channel_t *channel, switch_channel_flag_t want_flag, switch_bool_t pres, uint32_t to, switch_channel_t *super_channel)
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
switch_status_t switch_ivr_signal_bridge(switch_core_session_t *session, switch_core_session_t *peer_session)
Bridge Signalling from one session to another.
#define switch_assert(expr)
#define switch_channel_set_variable(_channel, _var, _val)
switch_status_t switch_ivr_generate_xml_cdr(switch_core_session_t *session, switch_xml_t *xml_cdr)
Generate an XML CDR report.
Definition: switch_ivr.c:2713
#define SWITCH_API_HANGUP_HOOK_VARIABLE
Definition: switch_types.h:174
switch_caller_profile_t * switch_channel_get_caller_profile(switch_channel_t *channel)
Retrieve the given channel's caller profile.
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
void switch_core_session_destroy_state(switch_core_session_t *session)
switch_call_cause_t switch_channel_get_cause(_In_ switch_channel_t *channel)
return the cause code for a given channel
switch_caller_profile_t * switch_channel_get_originator_caller_profile(switch_channel_t *channel)
Retrieve the given channel's originator caller profile.
void switch_core_state_machine_init(switch_memory_pool_t *pool)
switch_size_t cng_packet_count
Definition: switch_types.h:635
switch_status_t switch_ivr_parse_all_messages(switch_core_session_t *session)
Definition: switch_ivr.c:801