From a4a792488bca0dd89c586b3106c6220f2825e9c6 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 16 Apr 2014 06:02:44 +0500 Subject: [PATCH] add generic keepalive system and implement it in sofia to send MESSAGE or INFO packets in-dialog at specified interval. Adds app: enable_keepalive 0| This app can be run in the dialplan or with execute_on_* type variables for B-legs. Adds sofia param: keepalive-method : defaults to MESSAGE can also be "INFO" This param sets which SIP method to use. --- src/include/switch_types.h | 1 + .../applications/mod_dptools/mod_dptools.c | 29 +++++++++++++++++ src/mod/endpoints/mod_sofia/mod_sofia.c | 32 +++++++++++++++++++ src/mod/endpoints/mod_sofia/mod_sofia.h | 8 +++++ src/mod/endpoints/mod_sofia/sofia.c | 8 +++++ src/switch_core_io.c | 3 +- src/switch_core_session.c | 2 ++ 7 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index b9c5b744ac..18a829055b 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1009,6 +1009,7 @@ typedef enum { SWITCH_MESSAGE_INDICATE_BLIND_TRANSFER_RESPONSE, SWITCH_MESSAGE_INDICATE_STUN_ERROR, SWITCH_MESSAGE_INDICATE_MEDIA_RENEG, + SWITCH_MESSAGE_INDICATE_KEEPALIVE, SWITCH_MESSAGE_REFER_EVENT, SWITCH_MESSAGE_ANSWER_EVENT, SWITCH_MESSAGE_PROGRESS_EVENT, diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 6dbee87c95..1fcced7ac3 100644 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -552,6 +552,31 @@ SWITCH_STANDARD_APP(heartbeat_function) if (data) { seconds = atoi(data); if (seconds >= 0) { + + switch_core_session_enable_heartbeat(session, seconds); + return; + } + } + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", HEARTBEAT_SYNTAX); + +} + + +#define KEEPALIVE_SYNTAX "[0|]" +SWITCH_STANDARD_APP(keepalive_function) +{ + int seconds = 0; + + if (data) { + seconds = atoi(data); + if (seconds >= 0) { + switch_core_session_message_t msg = { 0 }; + + msg.message_id = SWITCH_MESSAGE_INDICATE_KEEPALIVE; + msg.numeric_arg = seconds; + switch_core_session_receive_message(session, &msg); + switch_core_session_enable_heartbeat(session, seconds); return; } @@ -5777,6 +5802,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) sched_heartbeat_function, SCHED_HEARTBEAT_SYNTAX, SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "enable_heartbeat", "Enable Media Heartbeat", "Enable Media Heartbeat", heartbeat_function, HEARTBEAT_SYNTAX, SAF_SUPPORT_NOMEDIA); + + SWITCH_ADD_APP(app_interface, "enable_keepalive", "Enable Keepalive", "Enable Keepalive", + keepalive_function, KEEPALIVE_SYNTAX, SAF_SUPPORT_NOMEDIA); + SWITCH_ADD_APP(app_interface, "media_reset", "Reset all bypass/proxy media flags", "Reset all bypass/proxy media flags", media_reset_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "mkdir", "Create a directory", "Create a directory", mkdir_function, MKDIR_SYNTAX, SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "rename", "Rename file", "Rename file", rename_function, RENAME_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ZOMBIE_EXEC); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index c70bc1771e..26ad9f4063 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1124,6 +1124,38 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi /* ones that do not need to lock sofia mutex */ switch (msg->message_id) { + case SWITCH_MESSAGE_INDICATE_KEEPALIVE: + { + if (msg->numeric_arg) { + sofia_set_flag_locked(tech_pvt, TFLAG_KEEPALIVE); + } else { + sofia_clear_flag_locked(tech_pvt, TFLAG_KEEPALIVE); + } + } + break; + case SWITCH_MESSAGE_HEARTBEAT_EVENT: + { + char pl[160] = ""; + + switch_snprintf(pl, sizeof(pl), "KEEP-ALIVE %d\n", ++tech_pvt->keepalive); + + if (sofia_test_flag(tech_pvt, TFLAG_KEEPALIVE)) { + if (tech_pvt->profile->keepalive == KA_MESSAGE) { + nua_message(tech_pvt->nh, + SIPTAG_CONTENT_TYPE_STR("text/plain"), + TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), + SIPTAG_PAYLOAD_STR(pl), + TAG_END()); + } else if (tech_pvt->profile->keepalive == KA_INFO) { + nua_info(tech_pvt->nh, + SIPTAG_CONTENT_TYPE_STR("text/plain"), + TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), + SIPTAG_PAYLOAD_STR(pl), + TAG_END()); + } + } + } + break; case SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH: case SWITCH_MESSAGE_INDICATE_APPLICATION_EXEC: break; diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index c9f3f12ce5..0c1f755c79 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -322,6 +322,7 @@ typedef enum { TFLAG_CAPTURE, TFLAG_REINVITED, TFLAG_PASS_ACK, + TFLAG_KEEPALIVE, /* No new flags below this line */ TFLAG_MAX } TFLAGS; @@ -534,6 +535,11 @@ typedef enum { #define MAX_RTPIP 50 +typedef enum { + KA_MESSAGE, + KA_INFO +} ka_type_t; + struct sofia_profile { int debug; int parse_invite_tel_params; @@ -706,6 +712,7 @@ struct sofia_profile { int tcp_keepalive; int tcp_pingpong; int tcp_ping2pong; + ka_type_t keepalive; }; @@ -772,6 +779,7 @@ struct private_object { int respond_code; char *respond_dest; time_t last_vid_info; + uint32_t keepalive; }; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 71cedf8886..79d39072e0 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -4025,6 +4025,14 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name) profile->debug = atoi(val); } else if (!strcasecmp(var, "parse-invite-tel-params")) { profile->parse_invite_tel_params = switch_true(val); + } else if (!strcasecmp(var, "keepalive-method")) { + if (!zstr(val)) { + if (!strcasecmp(val, "info")) { + profile->keepalive = KA_INFO; + } else { + profile->keepalive = KA_MESSAGE; + } + } } else if (!strcasecmp(var, "shutdown-on-fail")) { profile->shutdown_type = switch_core_strdup(profile->pool, val); } else if (!strcasecmp(var, "sip-trace") && switch_true(val)) { diff --git a/src/switch_core_io.c b/src/switch_core_io.c index 6b9a1dacf8..04b9ca46e3 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -231,8 +231,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi session->read_frame_count = (session->read_impl.actual_samples_per_second / session->read_impl.samples_per_packet) * session->track_duration; msg.message_id = SWITCH_MESSAGE_HEARTBEAT_EVENT; + msg.numeric_arg = session->track_duration; switch_core_session_receive_message(session, &msg); - + switch_event_create(&event, SWITCH_EVENT_SESSION_HEARTBEAT); switch_channel_event_set_data(session->channel, event); switch_event_fire(&event); diff --git a/src/switch_core_session.c b/src/switch_core_session.c index d07a435b74..228e765dad 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -751,6 +751,7 @@ static const char *message_names[] = { "BLIND_TRANSFER_RESPONSE", "STUN_ERROR", "MEDIA_RENEG", + "KEEPALIVE", "ANSWER_EVENT", "PROGRESS_EVENT", "RING_EVENT", @@ -1506,6 +1507,7 @@ SWITCH_STANDARD_SCHED_FUNC(sch_heartbeat_callback) task->runtime = switch_epoch_time_now(NULL) + session->track_duration; msg.message_id = SWITCH_MESSAGE_HEARTBEAT_EVENT; + msg.numeric_arg = session->track_duration; switch_core_session_receive_message(session, &msg); switch_core_session_rwunlock(session);