diff --git a/src/include/switch_types.h b/src/include/switch_types.h index ffd83211fa..853e17801f 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -885,6 +885,7 @@ typedef enum { CF_BLOCK_STATE, CF_FS_RTP, CF_REPORTING, + CF_PARK, /* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */ CF_FLAG_MAX } switch_channel_flag_t; diff --git a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c index 4876c2f011..a859606a6f 100644 --- a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c +++ b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c @@ -51,7 +51,9 @@ typedef enum { LFLAG_STATEFUL = (1 << 8), LFLAG_OUTBOUND = (1 << 9), LFLAG_LINGER = (1 << 10), - LFLAG_HANDLE_DISCO = (1 << 11) + LFLAG_HANDLE_DISCO = (1 << 11), + LFLAG_CONNECTED = (1 << 12), + LFLAG_RESUME = (1 << 13), } event_flag_t; typedef enum { @@ -422,9 +424,29 @@ SWITCH_STANDARD_APP(socket_function) } } - if (switch_test_flag(listener, LFLAG_ASYNC)) { + if (switch_test_flag(listener, LFLAG_ASYNC)) { + const char *var; + launch_listener_thread(listener); + + if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) { + return; + } + + while(switch_channel_ready(channel) && !switch_test_flag(listener, LFLAG_CONNECTED)) { + switch_cond_next(); + } + switch_ivr_park(session, NULL); + + if (switch_core_session_private_event_count(session)) { + switch_ivr_parse_all_events(session); + } + + if (switch_test_flag(listener, LFLAG_RESUME) || ((var = switch_channel_get_variable(channel, "socket_resume")) && switch_true(var))) { + switch_channel_set_state(channel, CS_EXECUTE); + } + return; } else { listener_run(NULL, (void *) listener); @@ -1425,7 +1447,13 @@ static switch_status_t parse_command(listener_t *listener, switch_event_t **even goto done; } - + + if (listener->session && !strncasecmp(cmd, "resume", 6)) { + switch_set_flag_locked(listener, LFLAG_RESUME); + switch_channel_set_variable(switch_core_session_get_channel(listener->session), "socket_resume", "true"); + switch_snprintf(reply, reply_len, "+OK"); + goto done; + } if (listener->session || !strncasecmp(cmd, "myevents ", 9)) { switch_channel_t *channel = NULL; @@ -1438,6 +1466,8 @@ static switch_status_t parse_command(listener_t *listener, switch_event_t **even switch_event_t *call_event; char *event_str; switch_size_t len; + + switch_set_flag_locked(listener, LFLAG_CONNECTED); switch_event_create(&call_event, SWITCH_EVENT_CHANNEL_DATA); switch_caller_profile_event_set_data(switch_channel_get_caller_profile(channel), "Channel", call_event); @@ -1935,6 +1965,7 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj) switch_core_session_t *session = NULL; switch_channel_t *channel = NULL; switch_event_t *revent = NULL; + const char *var; switch_mutex_lock(globals.listener_mutex); prefs.threads++; @@ -2084,6 +2115,12 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj) switch_event_destroy(&listener->filters); } switch_mutex_unlock(listener->filter_mutex); + + if (listener->session && (switch_test_flag(listener, LFLAG_RESUME) || + ((var = switch_channel_get_variable(channel, "socket_resume")) && switch_true(var)))) { + channel = switch_core_session_get_channel(listener->session); + switch_channel_set_state(channel, CS_RESET); + } if (listener->sock) { char disco_buf[512] = ""; const char message[] = "Disconnected, goodbye.\nSee you at ClueCon! http://www.cluecon.com/\n"; diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 9c4f2d5d25..23dfc2469a 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -650,9 +650,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session, switch_codec_implementation_t read_impl = {0}; switch_core_session_get_read_impl(session, &read_impl); - - - + if (switch_channel_test_flag(channel, CF_CONTROLLED)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot park channels that are under control already.\n"); return SWITCH_STATUS_FALSE; @@ -665,8 +663,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session, return SWITCH_STATUS_FALSE; } } - - if (switch_channel_test_flag(channel, CF_PROXY_MODE)) { + + if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_get_state(channel) == CS_RESET) { return SWITCH_STATUS_FALSE; } @@ -684,16 +682,20 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session, } else { expires = switch_epoch_time_now(NULL) + timeout; } + switch_channel_set_variable(channel, "park_timeout", NULL); } switch_channel_set_flag(channel, CF_CONTROLLED); + switch_channel_set_flag(channel, CF_PARK); + if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_PARK) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(channel, event); switch_event_fire(&event); } - while (switch_channel_media_ready(channel) && switch_channel_ready(channel) && switch_channel_test_flag(channel, CF_CONTROLLED)) { - + while (switch_channel_media_ready(channel) && switch_channel_ready(channel) && switch_channel_test_flag(channel, CF_CONTROLLED) + && switch_channel_test_flag(channel, CF_PARK)) { + if ((status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, stream_id)) == SWITCH_STATUS_SUCCESS) { if (!SWITCH_READ_ACCEPTABLE(status)) { break; @@ -798,6 +800,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session, } switch_channel_clear_flag(channel, CF_CONTROLLED); + switch_channel_clear_flag(channel, CF_PARK); if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_UNPARK) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(channel, event);