Asterisk - The Open Source Telephony Project  18.5.0
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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .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"

◆ SEND_TO_VM_HEADER

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

◆ 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.

Referenced by handle_incoming_request(), and has_call_feature().

◆ SEND_TO_VM_REDIRECT

#define SEND_TO_VM_REDIRECT   "REDIRECTING(reason)"

◆ 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.

Referenced by has_diversion_reason().

◆ 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.

Referenced by handle_incoming_request(), and has_diversion_reason().

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.

References ast_channel_cleanup, and ast_channel::data.

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

◆ 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.

References NULL, and value.

Referenced by has_diversion_reason().

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

◆ 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.

Referenced by has_diversion_reason().

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

◆ 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.

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(), ast_sip_session::channel, ast_datastore::data, DATASTORE_NAME, ast_sip_session::endpoint, 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, and SEND_TO_VM_REDIRECT_VALUE.

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 }
Main Channel structure associated with a channel.
struct ast_sip_endpoint * endpoint
static void send_response(struct ast_sip_session *session, int code, struct pjsip_rx_data *rdata)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
#define LOG_WARNING
Definition: logger.h:274
static struct ast_datastore_info call_feature_info
Structure for a data store object.
Definition: datastore.h:68
#define ast_log
Definition: astobj2.c:42
struct ast_datastore * ast_sip_session_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
Alternative for ast_datastore_alloc()
static int has_diversion_reason(pjsip_rx_data *rdata)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define SEND_TO_VM_REDIRECT_VALUE
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
struct ast_channel * channel
#define SEND_TO_VM_HEADER
#define DATASTORE_NAME
#define SEND_TO_VM_REDIRECT
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...
void * data
Definition: datastore.h:70
static int has_call_feature(pjsip_rx_data *rdata)
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel&#39;s bridge peer only if the bridge is two-party.
Definition: channel.c:10765
const char * ast_channel_name(const struct ast_channel *chan)
#define SEND_TO_VM_HEADER_VALUE
int ast_sip_session_add_datastore(struct ast_sip_session *session, struct ast_datastore *datastore)
Add a datastore to a SIP 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.

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, and status.

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 }
Main Channel structure associated with a channel.
Structure for a data store object.
Definition: datastore.h:68
#define NULL
Definition: resample.c:96
void ast_sip_session_remove_datastore(struct ast_sip_session *session, const char *name)
Remove a session datastore from the session.
struct ast_datastore * ast_sip_session_get_datastore(struct ast_sip_session *session, const char *name)
Retrieve a session datastore.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define SEND_TO_VM_HEADER
#define DATASTORE_NAME
#define SEND_TO_VM_REDIRECT
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...
void * data
Definition: datastore.h:70
jack_status_t status
Definition: app_jack.c:146

◆ 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.

References NULL, and SEND_TO_VM_HEADER_VALUE.

Referenced by handle_incoming_request().

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 }
#define NULL
Definition: resample.c:96
#define SEND_TO_VM_HEADER_VALUE

◆ 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.

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

Referenced by handle_incoming_request().

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 }
static pjsip_param * get_diversion_reason(pjsip_fromto_hdr *hdr)
#define SEND_TO_VM_REDIRECT_QUOTED_VALUE
static pjsip_fromto_hdr * get_diversion_header(pjsip_rx_data *rdata)
#define SEND_TO_VM_REDIRECT_VALUE

◆ load_module()

static int load_module ( void  )
static

Definition at line 216 of file res_pjsip_send_to_voicemail.c.

References AST_MODULE_LOAD_SUCCESS, and ast_sip_session_register_supplement.

Referenced by unload_module().

217 {
219 
221 }
static struct ast_sip_session_supplement refer_supplement
#define ast_sip_session_register_supplement(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.

References ast_sip_session::inv_session, and NULL.

Referenced by handle_incoming_request().

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 }
#define NULL
Definition: resample.c:96
struct pjsip_inv_session * inv_session

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 223 of file res_pjsip_send_to_voicemail.c.

References AST_MODFLAG_LOAD_ORDER, AST_MODPRI_APP_DEPEND, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ast_sip_session_unregister_supplement(), ASTERISK_GPL_KEY, and load_module().

224 {
226  return 0;
227 }
static struct ast_sip_session_supplement refer_supplement
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

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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .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.

◆ 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.