Asterisk - The Open Source Telephony Project GIT-master-f36a736
Macros | Functions | Variables
res_pjsip_send_to_voicemail.c File Reference

Module for managing send to voicemail requests in SIP REFER messages against PJSIP channels. More...

#include "asterisk.h"
#include <pjsip.h>
#include <pjsip_ua.h>
#include "asterisk/pbx.h"
#include "asterisk/res_pjsip.h"
#include "asterisk/res_pjsip_session.h"
#include "asterisk/module.h"
Include dependency graph for res_pjsip_send_to_voicemail.c:

Go to the source code of this file.

Macros

#define DATASTORE_NAME   "call_feature_send_to_vm_datastore"
 
#define SEND_TO_VM_HEADER   "PJSIP_HEADER(add,X-Digium-Call-Feature)"
 
#define SEND_TO_VM_HEADER_VALUE   "feature_send_to_vm"
 
#define SEND_TO_VM_REDIRECT   "REDIRECTING(reason)"
 
#define SEND_TO_VM_REDIRECT_QUOTED_VALUE   "\"" SEND_TO_VM_REDIRECT_VALUE "\""
 
#define SEND_TO_VM_REDIRECT_VALUE   "send_to_vm"
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static void channel_cleanup_wrapper (void *data)
 
static pjsip_fromto_hdr * get_diversion_header (pjsip_rx_data *rdata)
 
static pjsip_param * get_diversion_reason (pjsip_fromto_hdr *hdr)
 
static int handle_incoming_request (struct ast_sip_session *session, struct pjsip_rx_data *rdata)
 
static void handle_outgoing_response (struct ast_sip_session *session, struct pjsip_tx_data *tdata)
 
static int has_call_feature (pjsip_rx_data *rdata)
 
static int has_diversion_reason (pjsip_rx_data *rdata)
 
static int load_module (void)
 
static void send_response (struct ast_sip_session *session, int code, struct pjsip_rx_data *rdata)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP REFER Send to Voicemail Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_pjsip,res_pjsip_session", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_datastore_info call_feature_info
 
static struct ast_sip_session_supplement refer_supplement
 

Detailed Description

Module for managing send to voicemail requests in SIP REFER messages against PJSIP channels.

Author
Jonathan Rose jrose.nosp@m.@dig.nosp@m.ium.c.nosp@m.om

Definition in file res_pjsip_send_to_voicemail.c.

Macro Definition Documentation

◆ DATASTORE_NAME

#define DATASTORE_NAME   "call_feature_send_to_vm_datastore"

Definition at line 44 of file res_pjsip_send_to_voicemail.c.

◆ SEND_TO_VM_HEADER

#define SEND_TO_VM_HEADER   "PJSIP_HEADER(add,X-Digium-Call-Feature)"

Definition at line 46 of file res_pjsip_send_to_voicemail.c.

◆ SEND_TO_VM_HEADER_VALUE

#define SEND_TO_VM_HEADER_VALUE   "feature_send_to_vm"

Definition at line 47 of file res_pjsip_send_to_voicemail.c.

◆ SEND_TO_VM_REDIRECT

#define SEND_TO_VM_REDIRECT   "REDIRECTING(reason)"

Definition at line 49 of file res_pjsip_send_to_voicemail.c.

◆ SEND_TO_VM_REDIRECT_QUOTED_VALUE

#define SEND_TO_VM_REDIRECT_QUOTED_VALUE   "\"" SEND_TO_VM_REDIRECT_VALUE "\""

Definition at line 51 of file res_pjsip_send_to_voicemail.c.

◆ SEND_TO_VM_REDIRECT_VALUE

#define SEND_TO_VM_REDIRECT_VALUE   "send_to_vm"

Definition at line 50 of file res_pjsip_send_to_voicemail.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 235 of file res_pjsip_send_to_voicemail.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 235 of file res_pjsip_send_to_voicemail.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 235 of file res_pjsip_send_to_voicemail.c.

◆ channel_cleanup_wrapper()

static void channel_cleanup_wrapper ( void *  data)
static

Definition at line 64 of file res_pjsip_send_to_voicemail.c.

65{
66 struct ast_channel *chan = data;
68}
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:3015
Main Channel structure associated with a channel.
const char * data

References ast_channel_cleanup, and ast_channel::data.

◆ get_diversion_header()

static pjsip_fromto_hdr * get_diversion_header ( pjsip_rx_data *  rdata)
static

Definition at line 81 of file res_pjsip_send_to_voicemail.c.

82{
83 static const pj_str_t from_str = { "From", 4 };
84 static const pj_str_t diversion_str = { "Diversion", 9 };
85
86 pjsip_generic_string_hdr *hdr;
87 pj_str_t value;
88
89 if (!(hdr = pjsip_msg_find_hdr_by_name(
90 rdata->msg_info.msg, &diversion_str, NULL))) {
91 return NULL;
92 }
93
94 pj_strdup_with_null(rdata->tp_info.pool, &value, &hdr->hvalue);
95
96 /* parse as a fromto header */
97 return pjsip_parse_hdr(rdata->tp_info.pool, &from_str, value.ptr,
98 pj_strlen(&value), NULL);
99}
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37

References NULL, and value.

Referenced by has_diversion_reason().

◆ get_diversion_reason()

static pjsip_param * get_diversion_reason ( pjsip_fromto_hdr *  hdr)
static

Definition at line 75 of file res_pjsip_send_to_voicemail.c.

76{
77 static const pj_str_t reason_str = { "reason", 6 };
78 return pjsip_param_find(&hdr->other_param, &reason_str);
79}

Referenced by has_diversion_reason().

◆ handle_incoming_request()

static int handle_incoming_request ( struct ast_sip_session session,
struct pjsip_rx_data *  rdata 
)
static

Definition at line 125 of file res_pjsip_send_to_voicemail.c.

126{
127 struct ast_datastore *sip_session_datastore;
128 struct ast_channel *other_party;
129 int has_feature;
130 int has_reason;
131
132 if (!session->channel) {
133 return 0;
134 }
135
136 has_feature = has_call_feature(rdata);
137 has_reason = has_diversion_reason(rdata);
138 if (!has_feature && !has_reason) {
139 /* If we don't have a call feature or diversion reason or if
140 it's not a feature this module is related to then there
141 is nothing to do. */
142 return 0;
143 }
144
145 /* Check bridge status... */
146 other_party = ast_channel_bridge_peer(session->channel);
147 if (!other_party) {
148 /* The channel wasn't in a two party bridge */
149 ast_log(LOG_WARNING, "%s (%s) attempted to transfer to voicemail, "
150 "but was not in a two party bridge.\n",
152 ast_channel_name(session->channel));
153 send_response(session, 400, rdata);
154 return -1;
155 }
156
157 sip_session_datastore = ast_sip_session_alloc_datastore(
159 if (!sip_session_datastore) {
160 ast_channel_unref(other_party);
161 send_response(session, 500, rdata);
162 return -1;
163 }
164
165 sip_session_datastore->data = other_party;
166
167 if (ast_sip_session_add_datastore(session, sip_session_datastore)) {
168 ao2_ref(sip_session_datastore, -1);
169 send_response(session, 500, rdata);
170 return -1;
171 }
172
173 if (has_feature) {
176 }
177
178 if (has_reason) {
181 }
182
183 ao2_ref(sip_session_datastore, -1);
184 return 0;
185}
static struct ast_mansession session
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
Definition: channel.c:10586
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3004
#define LOG_WARNING
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
static void send_response(struct ast_sip_session *session, int code, struct pjsip_rx_data *rdata)
#define SEND_TO_VM_HEADER_VALUE
#define SEND_TO_VM_REDIRECT_VALUE
static int has_diversion_reason(pjsip_rx_data *rdata)
static struct ast_datastore_info call_feature_info
#define SEND_TO_VM_REDIRECT
#define DATASTORE_NAME
static int has_call_feature(pjsip_rx_data *rdata)
#define SEND_TO_VM_HEADER
int ast_sip_session_add_datastore(struct ast_sip_session *session, struct ast_datastore *datastore)
Add a datastore to a SIP session.
struct ast_datastore * ast_sip_session_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
Alternative for ast_datastore_alloc()
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2317
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66

References ao2_ref, ast_channel_bridge_peer(), ast_channel_name(), ast_channel_unref, ast_log, ast_sip_session_add_datastore(), ast_sip_session_alloc_datastore(), ast_sorcery_object_get_id(), call_feature_info, ast_datastore::data, DATASTORE_NAME, has_call_feature(), has_diversion_reason(), LOG_WARNING, pbx_builtin_setvar_helper(), send_response(), SEND_TO_VM_HEADER, SEND_TO_VM_HEADER_VALUE, SEND_TO_VM_REDIRECT, SEND_TO_VM_REDIRECT_VALUE, and session.

◆ handle_outgoing_response()

static void handle_outgoing_response ( struct ast_sip_session session,
struct pjsip_tx_data *  tdata 
)
static

Definition at line 187 of file res_pjsip_send_to_voicemail.c.

188{
189 pjsip_status_line status = tdata->msg->line.status;
190 struct ast_datastore *feature_datastore =
192 struct ast_channel *target_chan;
193
194 if (!feature_datastore) {
195 return;
196 }
197
198 /* Since we are handling the response, there is no need to keep the datastore in the session anymore. */
200
201 /* If the response >= 300, the refer failed and we need to clear the feature. */
202 if (status.code >= 300) {
203 target_chan = feature_datastore->data;
206 }
207 ao2_ref(feature_datastore, -1);
208}
jack_status_t status
Definition: app_jack.c:146
struct ast_datastore * ast_sip_session_get_datastore(struct ast_sip_session *session, const char *name)
Retrieve a session datastore.
void ast_sip_session_remove_datastore(struct ast_sip_session *session, const char *name)
Remove a session datastore from the session.

References ao2_ref, ast_sip_session_get_datastore(), ast_sip_session_remove_datastore(), ast_datastore::data, DATASTORE_NAME, NULL, pbx_builtin_setvar_helper(), SEND_TO_VM_HEADER, SEND_TO_VM_REDIRECT, session, and status.

◆ has_call_feature()

static int has_call_feature ( pjsip_rx_data *  rdata)
static

Definition at line 115 of file res_pjsip_send_to_voicemail.c.

116{
117 static const pj_str_t call_feature_str = { "X-Digium-Call-Feature", 21 };
118
119 pjsip_generic_string_hdr *hdr = pjsip_msg_find_hdr_by_name(
120 rdata->msg_info.msg, &call_feature_str, NULL);
121
122 return hdr && !pj_stricmp2(&hdr->hvalue, SEND_TO_VM_HEADER_VALUE);
123}

References NULL, and SEND_TO_VM_HEADER_VALUE.

Referenced by handle_incoming_request().

◆ has_diversion_reason()

static int has_diversion_reason ( pjsip_rx_data *  rdata)
static

Definition at line 101 of file res_pjsip_send_to_voicemail.c.

102{
103 pjsip_param *reason;
104 pjsip_fromto_hdr *hdr = get_diversion_header(rdata);
105
106 if (!hdr) {
107 return 0;
108 }
109 reason = get_diversion_reason(hdr);
110 return reason
111 && (!pj_stricmp2(&reason->value, SEND_TO_VM_REDIRECT_QUOTED_VALUE)
112 || !pj_stricmp2(&reason->value, SEND_TO_VM_REDIRECT_VALUE));
113}
#define SEND_TO_VM_REDIRECT_QUOTED_VALUE
static pjsip_fromto_hdr * get_diversion_header(pjsip_rx_data *rdata)
static pjsip_param * get_diversion_reason(pjsip_fromto_hdr *hdr)

References get_diversion_header(), get_diversion_reason(), SEND_TO_VM_REDIRECT_QUOTED_VALUE, and SEND_TO_VM_REDIRECT_VALUE.

Referenced by handle_incoming_request().

◆ load_module()

static int load_module ( void  )
static

Definition at line 216 of file res_pjsip_send_to_voicemail.c.

217{
219
221}
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
static struct ast_sip_session_supplement refer_supplement
#define ast_sip_session_register_supplement(supplement)

References AST_MODULE_LOAD_SUCCESS, ast_sip_session_register_supplement, and refer_supplement.

◆ send_response()

static void send_response ( struct ast_sip_session session,
int  code,
struct pjsip_rx_data *  rdata 
)
static

Definition at line 53 of file res_pjsip_send_to_voicemail.c.

54{
55 pjsip_tx_data *tdata;
56
57 if (pjsip_dlg_create_response(session->inv_session->dlg, rdata, code, NULL, &tdata) == PJ_SUCCESS) {
58 struct pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
59
60 pjsip_dlg_send_response(session->inv_session->dlg, tsx, tdata);
61 }
62}

References NULL, and session.

Referenced by handle_incoming_request().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 223 of file res_pjsip_send_to_voicemail.c.

224{
226 return 0;
227}
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
Unregister a an supplement to SIP session processing.
Definition: pjsip_session.c:63

References ast_sip_session_unregister_supplement(), and refer_supplement.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP REFER Send to Voicemail Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_pjsip,res_pjsip_session", }
static

Definition at line 235 of file res_pjsip_send_to_voicemail.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 235 of file res_pjsip_send_to_voicemail.c.

◆ call_feature_info

struct ast_datastore_info call_feature_info
static
Initial value:
= {
.type = "REFER call feature info",
}
static void channel_cleanup_wrapper(void *data)

Definition at line 70 of file res_pjsip_send_to_voicemail.c.

Referenced by handle_incoming_request().

◆ refer_supplement

struct ast_sip_session_supplement refer_supplement
static
Initial value:
= {
.method = "REFER",
.incoming_request = handle_incoming_request,
.outgoing_response = handle_outgoing_response,
}
static int handle_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
static void handle_outgoing_response(struct ast_sip_session *session, struct pjsip_tx_data *tdata)

Definition at line 210 of file res_pjsip_send_to_voicemail.c.

Referenced by load_module(), and unload_module().