execute hangup state asap
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@14852 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
c92cb7283a
commit
5a5f3081f0
|
@ -87,13 +87,15 @@
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SSF_NONE = 0,
|
SSF_NONE = 0,
|
||||||
SSF_DESTROYED = (1 << 0),
|
SSF_DESTROYED = (1 << 0),
|
||||||
SSF_WARN_TRANSCODE = (1 << 1)
|
SSF_WARN_TRANSCODE = (1 << 1),
|
||||||
|
SSF_HANGUP = (1 << 2)
|
||||||
} switch_session_flag_t;
|
} switch_session_flag_t;
|
||||||
|
|
||||||
|
|
||||||
struct switch_core_session {
|
struct switch_core_session {
|
||||||
switch_memory_pool_t *pool;
|
switch_memory_pool_t *pool;
|
||||||
switch_thread_t *thread;
|
switch_thread_t *thread;
|
||||||
|
switch_thread_id_t thread_id;
|
||||||
switch_endpoint_interface_t *endpoint_interface;
|
switch_endpoint_interface_t *endpoint_interface;
|
||||||
switch_size_t id;
|
switch_size_t id;
|
||||||
switch_session_flag_t flags;
|
switch_session_flag_t flags;
|
||||||
|
|
|
@ -591,6 +591,7 @@ SWITCH_DECLARE(void) switch_core_session_perform_destroy(_Inout_ switch_core_ses
|
||||||
|
|
||||||
SWITCH_DECLARE(void) switch_core_session_destroy_state(switch_core_session_t *session);
|
SWITCH_DECLARE(void) switch_core_session_destroy_state(switch_core_session_t *session);
|
||||||
SWITCH_DECLARE(void) switch_core_session_reporting_state(switch_core_session_t *session);
|
SWITCH_DECLARE(void) switch_core_session_reporting_state(switch_core_session_t *session);
|
||||||
|
SWITCH_DECLARE(void) switch_core_session_hangup_state(switch_core_session_t *session);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Provide the total number of sessions
|
\brief Provide the total number of sessions
|
||||||
|
|
|
@ -260,7 +260,7 @@ SWITCH_DECLARE(void) consoleCleanLog(char *msg);
|
||||||
* \return an int status code indicating success or failure
|
* \return an int status code indicating success or failure
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
SWITCH_DECLARE(int) originate(CoreSession * a_leg_session, char *dest, int timeout = 60);
|
SWITCH_DECLARE(int) originate(CoreSession * a_leg_session, char *dest, int timeout = 60, switch_state_handler_table_t *handlers = NULL);
|
||||||
|
|
||||||
|
|
||||||
SWITCH_DECLARE(virtual void) destroy(void);
|
SWITCH_DECLARE(virtual void) destroy(void);
|
||||||
|
|
|
@ -6048,6 +6048,14 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_session_reporting_state(void * ja
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_session_hangup_state(void * jarg1) {
|
||||||
|
switch_core_session_t *arg1 = (switch_core_session_t *) 0 ;
|
||||||
|
|
||||||
|
arg1 = (switch_core_session_t *)jarg1;
|
||||||
|
switch_core_session_hangup_state(arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_core_session_count() {
|
SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_core_session_count() {
|
||||||
unsigned long jresult ;
|
unsigned long jresult ;
|
||||||
uint32_t result;
|
uint32_t result;
|
||||||
|
@ -28592,19 +28600,21 @@ SWIGEXPORT void SWIGSTDCALL CSharp_CoreSession_SetCallerData(void * jarg1, char
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SWIGEXPORT int SWIGSTDCALL CSharp_CoreSession_Originate(void * jarg1, void * jarg2, char * jarg3, int jarg4) {
|
SWIGEXPORT int SWIGSTDCALL CSharp_CoreSession_Originate(void * jarg1, void * jarg2, char * jarg3, int jarg4, void * jarg5) {
|
||||||
int jresult ;
|
int jresult ;
|
||||||
CoreSession *arg1 = (CoreSession *) 0 ;
|
CoreSession *arg1 = (CoreSession *) 0 ;
|
||||||
CoreSession *arg2 = (CoreSession *) 0 ;
|
CoreSession *arg2 = (CoreSession *) 0 ;
|
||||||
char *arg3 = (char *) 0 ;
|
char *arg3 = (char *) 0 ;
|
||||||
int arg4 = (int) 60 ;
|
int arg4 = (int) 60 ;
|
||||||
|
switch_state_handler_table_t *arg5 = (switch_state_handler_table_t *) NULL ;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
arg1 = (CoreSession *)jarg1;
|
arg1 = (CoreSession *)jarg1;
|
||||||
arg2 = (CoreSession *)jarg2;
|
arg2 = (CoreSession *)jarg2;
|
||||||
arg3 = (char *)jarg3;
|
arg3 = (char *)jarg3;
|
||||||
arg4 = (int)jarg4;
|
arg4 = (int)jarg4;
|
||||||
result = (int)(arg1)->originate(arg2,arg3,arg4);
|
arg5 = (switch_state_handler_table_t *)jarg5;
|
||||||
|
result = (int)(arg1)->originate(arg2,arg3,arg4,arg5);
|
||||||
jresult = result;
|
jresult = result;
|
||||||
return jresult;
|
return jresult;
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,8 +244,8 @@ public class CoreSession : IDisposable {
|
||||||
freeswitchPINVOKE.CoreSession_SetCallerData(swigCPtr, var, val);
|
freeswitchPINVOKE.CoreSession_SetCallerData(swigCPtr, var, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Originate(CoreSession a_leg_session, string dest, int timeout) {
|
public int Originate(CoreSession a_leg_session, string dest, int timeout, switch_state_handler_table handlers) {
|
||||||
int ret = freeswitchPINVOKE.CoreSession_Originate(swigCPtr, CoreSession.getCPtr(a_leg_session), dest, timeout);
|
int ret = freeswitchPINVOKE.CoreSession_Originate(swigCPtr, CoreSession.getCPtr(a_leg_session), dest, timeout, switch_state_handler_table.getCPtr(handlers));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1142,6 +1142,10 @@ public class freeswitch {
|
||||||
freeswitchPINVOKE.switch_core_session_reporting_state(SWIGTYPE_p_switch_core_session.getCPtr(session));
|
freeswitchPINVOKE.switch_core_session_reporting_state(SWIGTYPE_p_switch_core_session.getCPtr(session));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void switch_core_session_hangup_state(SWIGTYPE_p_switch_core_session session) {
|
||||||
|
freeswitchPINVOKE.switch_core_session_hangup_state(SWIGTYPE_p_switch_core_session.getCPtr(session));
|
||||||
|
}
|
||||||
|
|
||||||
public static uint switch_core_session_count() {
|
public static uint switch_core_session_count() {
|
||||||
uint ret = freeswitchPINVOKE.switch_core_session_count();
|
uint ret = freeswitchPINVOKE.switch_core_session_count();
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -6008,6 +6012,9 @@ class freeswitchPINVOKE {
|
||||||
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_reporting_state")]
|
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_reporting_state")]
|
||||||
public static extern void switch_core_session_reporting_state(HandleRef jarg1);
|
public static extern void switch_core_session_reporting_state(HandleRef jarg1);
|
||||||
|
|
||||||
|
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_hangup_state")]
|
||||||
|
public static extern void switch_core_session_hangup_state(HandleRef jarg1);
|
||||||
|
|
||||||
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_count")]
|
[DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_count")]
|
||||||
public static extern uint switch_core_session_count();
|
public static extern uint switch_core_session_count();
|
||||||
|
|
||||||
|
@ -11289,7 +11296,7 @@ class freeswitchPINVOKE {
|
||||||
public static extern void CoreSession_SetCallerData(HandleRef jarg1, string jarg2, string jarg3);
|
public static extern void CoreSession_SetCallerData(HandleRef jarg1, string jarg2, string jarg3);
|
||||||
|
|
||||||
[DllImport("mod_managed", EntryPoint="CSharp_CoreSession_Originate")]
|
[DllImport("mod_managed", EntryPoint="CSharp_CoreSession_Originate")]
|
||||||
public static extern int CoreSession_Originate(HandleRef jarg1, HandleRef jarg2, string jarg3, int jarg4);
|
public static extern int CoreSession_Originate(HandleRef jarg1, HandleRef jarg2, string jarg3, int jarg4, HandleRef jarg5);
|
||||||
|
|
||||||
[DllImport("mod_managed", EntryPoint="CSharp_CoreSession_destroy")]
|
[DllImport("mod_managed", EntryPoint="CSharp_CoreSession_destroy")]
|
||||||
public static extern void CoreSession_destroy(HandleRef jarg1);
|
public static extern void CoreSession_destroy(HandleRef jarg1);
|
||||||
|
|
|
@ -1714,6 +1714,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_hangup(switch_chan
|
||||||
|
|
||||||
switch_core_session_kill_channel(channel->session, SWITCH_SIG_KILL);
|
switch_core_session_kill_channel(channel->session, SWITCH_SIG_KILL);
|
||||||
switch_core_session_signal_state_change(channel->session);
|
switch_core_session_signal_state_change(channel->session);
|
||||||
|
switch_core_session_hangup_state(channel->session);
|
||||||
}
|
}
|
||||||
|
|
||||||
return channel->state;
|
return channel->state;
|
||||||
|
|
|
@ -1062,7 +1062,8 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread_t *thre
|
||||||
const char *val;
|
const char *val;
|
||||||
|
|
||||||
session->thread = thread;
|
session->thread = thread;
|
||||||
|
session->thread_id = switch_thread_self();
|
||||||
|
|
||||||
switch_core_session_run(session);
|
switch_core_session_run(session);
|
||||||
switch_core_media_bug_remove_all(session);
|
switch_core_media_bug_remove_all(session);
|
||||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Session %" SWITCH_SIZE_T_FMT " (%s) Locked, Waiting on external entities\n",
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Session %" SWITCH_SIZE_T_FMT " (%s) Locked, Waiting on external entities\n",
|
||||||
|
@ -1207,6 +1208,7 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_uuid(switch_
|
||||||
|
|
||||||
session = switch_core_alloc(usepool, sizeof(*session));
|
session = switch_core_alloc(usepool, sizeof(*session));
|
||||||
session->pool = usepool;
|
session->pool = usepool;
|
||||||
|
session->thread_id = switch_thread_self();
|
||||||
|
|
||||||
switch_core_memory_pool_set_data(session->pool, "__session", session);
|
switch_core_memory_pool_set_data(session->pool, "__session", session);
|
||||||
|
|
||||||
|
|
|
@ -413,69 +413,7 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session)
|
||||||
goto done;
|
goto done;
|
||||||
case CS_HANGUP: /* Deactivate and end the thread */
|
case CS_HANGUP: /* Deactivate and end the thread */
|
||||||
{
|
{
|
||||||
const char *hook_var;
|
switch_core_session_hangup_state(session);
|
||||||
switch_core_session_t *use_session = NULL;
|
|
||||||
switch_call_cause_t cause = switch_channel_get_cause(session->channel);
|
|
||||||
switch_call_cause_t cause_q850 = switch_channel_get_cause_q850(session->channel);
|
|
||||||
switch_event_t *event;
|
|
||||||
|
|
||||||
switch_channel_set_hangup_time(session->channel);
|
|
||||||
|
|
||||||
switch_core_media_bug_remove_all(session);
|
|
||||||
|
|
||||||
switch_channel_stop_broadcast(session->channel);
|
|
||||||
|
|
||||||
switch_channel_set_variable(session->channel, "hangup_cause", switch_channel_cause2str(cause));
|
|
||||||
switch_channel_set_variable_printf(session->channel, "hangup_cause_q850", "%d", cause_q850);
|
|
||||||
switch_channel_presence(session->channel, "unknown", switch_channel_cause2str(cause), NULL);
|
|
||||||
|
|
||||||
switch_channel_set_timestamps(session->channel);
|
|
||||||
|
|
||||||
STATE_MACRO(hangup, "HANGUP");
|
|
||||||
|
|
||||||
hook_var = switch_channel_get_variable(session->channel, SWITCH_API_HANGUP_HOOK_VARIABLE);
|
|
||||||
if (switch_true(switch_channel_get_variable(session->channel, SWITCH_SESSION_IN_HANGUP_HOOK_VARIABLE))) {
|
|
||||||
use_session = session;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!switch_strlen_zero(hook_var)) {
|
|
||||||
switch_stream_handle_t stream = { 0 };
|
|
||||||
char *cmd = switch_core_session_strdup(session, hook_var);
|
|
||||||
char *arg = NULL;
|
|
||||||
char *expanded = NULL;
|
|
||||||
|
|
||||||
if ((arg = strchr(cmd, ':')) && *(arg+1) == ':') {
|
|
||||||
*arg++ = '\0';
|
|
||||||
*arg++ = '\0';
|
|
||||||
} else {
|
|
||||||
if ((arg = strchr(cmd, ' '))) {
|
|
||||||
*arg++ = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SWITCH_STANDARD_STREAM(stream);
|
|
||||||
|
|
||||||
switch_channel_get_variables(session->channel, &stream.param_event);
|
|
||||||
switch_channel_event_set_data(session->channel, stream.param_event);
|
|
||||||
expanded = switch_channel_expand_variables(session->channel, arg);
|
|
||||||
|
|
||||||
switch_api_execute(cmd, expanded, use_session, &stream);
|
|
||||||
|
|
||||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Hangup Command %s(%s):\n%s\n", cmd, switch_str_nil(expanded),
|
|
||||||
switch_str_nil((char *) stream.data));
|
|
||||||
|
|
||||||
if (expanded != arg) {
|
|
||||||
switch_safe_free(expanded);
|
|
||||||
}
|
|
||||||
switch_safe_free(stream.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE) == SWITCH_STATUS_SUCCESS) {
|
|
||||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Hangup-Cause", switch_channel_cause2str(cause));
|
|
||||||
switch_channel_event_set_data(session->channel, event);
|
|
||||||
switch_event_fire(&event);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch_channel_set_state(session->channel, CS_REPORTING);
|
switch_channel_set_state(session->channel, CS_REPORTING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,6 +495,8 @@ SWITCH_DECLARE(void) switch_core_session_destroy_state(switch_core_session_t *se
|
||||||
|
|
||||||
switch_assert(session != NULL);
|
switch_assert(session != NULL);
|
||||||
switch_channel_set_running_state(session->channel, CS_DESTROY);
|
switch_channel_set_running_state(session->channel, CS_DESTROY);
|
||||||
|
switch_channel_clear_flag(session->channel, CF_TRANSFER);
|
||||||
|
switch_channel_clear_flag(session->channel, CF_REDIRECT);
|
||||||
|
|
||||||
session->thread_running = 1;
|
session->thread_running = 1;
|
||||||
endpoint_interface = session->endpoint_interface;
|
endpoint_interface = session->endpoint_interface;
|
||||||
|
@ -571,6 +511,101 @@ SWITCH_DECLARE(void) switch_core_session_destroy_state(switch_core_session_t *se
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SWITCH_DECLARE(void) switch_core_session_hangup_state(switch_core_session_t *session)
|
||||||
|
{
|
||||||
|
const char *hook_var;
|
||||||
|
switch_core_session_t *use_session = NULL;
|
||||||
|
switch_call_cause_t cause = switch_channel_get_cause(session->channel);
|
||||||
|
switch_call_cause_t cause_q850 = switch_channel_get_cause_q850(session->channel);
|
||||||
|
switch_event_t *event;
|
||||||
|
int proceed = 1;
|
||||||
|
int global_proceed = 1;
|
||||||
|
int do_extra_handlers = 1;
|
||||||
|
int silly = 0;
|
||||||
|
int index = 0;
|
||||||
|
switch_channel_state_t state = switch_channel_get_state(session->channel), midstate = state;
|
||||||
|
const switch_endpoint_interface_t *endpoint_interface;
|
||||||
|
const switch_state_handler_table_t *driver_state_handler = NULL;
|
||||||
|
const switch_state_handler_table_t *application_state_handler = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
if (switch_thread_self() != session->thread_id) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "thread mismatch skipping state handler.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (switch_test_flag(session, SSF_HANGUP)) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "handler already called, skipping state handler.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint_interface = session->endpoint_interface;
|
||||||
|
switch_assert(endpoint_interface != NULL);
|
||||||
|
|
||||||
|
driver_state_handler = endpoint_interface->state_handler;
|
||||||
|
switch_assert(driver_state_handler != NULL);
|
||||||
|
|
||||||
|
switch_channel_set_hangup_time(session->channel);
|
||||||
|
|
||||||
|
switch_core_media_bug_remove_all(session);
|
||||||
|
|
||||||
|
switch_channel_stop_broadcast(session->channel);
|
||||||
|
|
||||||
|
switch_channel_set_variable(session->channel, "hangup_cause", switch_channel_cause2str(cause));
|
||||||
|
switch_channel_set_variable_printf(session->channel, "hangup_cause_q850", "%d", cause_q850);
|
||||||
|
switch_channel_presence(session->channel, "unknown", switch_channel_cause2str(cause), NULL);
|
||||||
|
|
||||||
|
switch_channel_set_timestamps(session->channel);
|
||||||
|
|
||||||
|
STATE_MACRO(hangup, "HANGUP");
|
||||||
|
|
||||||
|
hook_var = switch_channel_get_variable(session->channel, SWITCH_API_HANGUP_HOOK_VARIABLE);
|
||||||
|
if (switch_true(switch_channel_get_variable(session->channel, SWITCH_SESSION_IN_HANGUP_HOOK_VARIABLE))) {
|
||||||
|
use_session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!switch_strlen_zero(hook_var)) {
|
||||||
|
switch_stream_handle_t stream = { 0 };
|
||||||
|
char *cmd = switch_core_session_strdup(session, hook_var);
|
||||||
|
char *arg = NULL;
|
||||||
|
char *expanded = NULL;
|
||||||
|
|
||||||
|
if ((arg = strchr(cmd, ':')) && *(arg+1) == ':') {
|
||||||
|
*arg++ = '\0';
|
||||||
|
*arg++ = '\0';
|
||||||
|
} else {
|
||||||
|
if ((arg = strchr(cmd, ' '))) {
|
||||||
|
*arg++ = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_STANDARD_STREAM(stream);
|
||||||
|
|
||||||
|
switch_channel_get_variables(session->channel, &stream.param_event);
|
||||||
|
switch_channel_event_set_data(session->channel, stream.param_event);
|
||||||
|
expanded = switch_channel_expand_variables(session->channel, arg);
|
||||||
|
|
||||||
|
switch_api_execute(cmd, expanded, use_session, &stream);
|
||||||
|
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Hangup Command %s(%s):\n%s\n", cmd, switch_str_nil(expanded),
|
||||||
|
switch_str_nil((char *) stream.data));
|
||||||
|
|
||||||
|
if (expanded != arg) {
|
||||||
|
switch_safe_free(expanded);
|
||||||
|
}
|
||||||
|
switch_safe_free(stream.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Hangup-Cause", switch_channel_cause2str(cause));
|
||||||
|
switch_channel_event_set_data(session->channel, event);
|
||||||
|
switch_event_fire(&event);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_set_flag(session, SSF_HANGUP);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(void) switch_core_session_reporting_state(switch_core_session_t *session)
|
SWITCH_DECLARE(void) switch_core_session_reporting_state(switch_core_session_t *session)
|
||||||
{
|
{
|
||||||
switch_channel_state_t state = switch_channel_get_state(session->channel), midstate = state;
|
switch_channel_state_t state = switch_channel_get_state(session->channel), midstate = state;
|
||||||
|
|
|
@ -932,7 +932,7 @@ SWITCH_DECLARE(void) CoreSession::destroy(void)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(int) CoreSession::originate(CoreSession *a_leg_session, char *dest, int timeout)
|
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;
|
switch_core_session_t *aleg_core_session = NULL;
|
||||||
|
@ -957,7 +957,7 @@ SWITCH_DECLARE(int) CoreSession::originate(CoreSession *a_leg_session, char *des
|
||||||
&cause,
|
&cause,
|
||||||
dest,
|
dest,
|
||||||
timeout,
|
timeout,
|
||||||
NULL,
|
handlers,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
&caller_profile,
|
&caller_profile,
|
||||||
|
|
Loading…
Reference in New Issue