Asterisk - The Open Source Telephony Project GIT-master-b023714
Loading...
Searching...
No Matches
res_pjsip_rfc3326.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2013, Digium, Inc.
5 *
6 * Joshua Colp <jcolp@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*** MODULEINFO
20 <depend>pjproject</depend>
21 <depend>res_pjsip</depend>
22 <depend>res_pjsip_session</depend>
23 <support_level>core</support_level>
24 ***/
25
26#include "asterisk.h"
27
28#include <pjsip.h>
29#include <pjsip_ua.h>
30
31#include "asterisk/res_pjsip.h"
33#include "asterisk/module.h"
34#include "asterisk/causes.h"
35#include "asterisk/threadpool.h"
36
37static void rfc3326_use_reason_header(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
38{
39 static const pj_str_t str_reason = { "Reason", 6 };
40 pjsip_generic_string_hdr *header;
41 char buf[128];
42 char *cause;
43 int code_q850 = 0, code_sip = 0;
44
45 header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_reason, NULL);
46 for (; header;
47 header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_reason, header->next)) {
48 int cause_q850, cause_sip;
49 struct ast_control_pvt_cause_code *cause_code;
50 int data_size = sizeof(*cause_code);
51
52 ast_copy_pj_str(buf, &header->hvalue, sizeof(buf));
53 cause = ast_skip_blanks(buf);
54 cause_q850 = !strncasecmp(cause, "Q.850", 5);
55 cause_sip = !strncasecmp(cause, "SIP", 3);
56 if ((cause_q850 || cause_sip) && (cause = strstr(cause, "cause="))) {
57 int *code = cause_q850 ? &code_q850 : &code_sip;
58 if (sscanf(cause, "cause=%30d", code) != 1) {
59 *code = 0;
60 }
61
62 /* Safe */
63 /* Build and send the tech-specific cause information */
64 /* size of the string making up the cause code is "SIP " + reason length */
65 data_size += 4 + strlen(cause) + 1;
66 cause_code = ast_alloca(data_size);
67 memset(cause_code, 0, data_size);
69 snprintf(cause_code->code, data_size, "SIP %s", cause);
70
71 cause_code->cause_extended = 1;
72 if (code_q850) {
73 cause_code->ast_cause = *code & 0x7;
74 } else if (code_sip) {
76 }
77 ast_queue_control_data(session->channel, AST_CONTROL_PVT_CAUSE_CODE, cause_code, data_size);
78 ast_channel_hangupcause_hash_set(session->channel, cause_code, data_size);
79 }
80 }
81
82 if (code_q850) {
83 ast_channel_hangupcause_set(session->channel, code_q850 & 0x7f);
84 } else if (code_sip) {
86 }
87}
88
89static int rfc3326_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
90{
91 if ((pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_bye_method) &&
92 pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_cancel_method)) ||
93 !session->channel) {
94 return 0;
95 }
96
98
99 return 0;
100}
101
102static void rfc3326_incoming_response(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
103{
104 struct pjsip_status_line status = rdata->msg_info.msg->line.status;
105
106 if ((status.code < 300) || !session->channel) {
107 return;
108 }
109
111}
112
113static void rfc3326_add_reason_header(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
114{
115 char buf[20];
116
118 ast_sip_add_header(tdata, "Reason", "SIP;cause=200;text=\"Call completed elsewhere\"");
119 }
120
121 if (session->endpoint && session->endpoint->suppress_q850_reason_headers) {
122 ast_debug(1, "A Q.850 '%s'(%i) Reason header was suppressed for endpoint '%s'\n",
124 (ast_channel_hangupcause(session->channel) & 0x7f),
126 } else {
127 snprintf(buf, sizeof(buf), "Q.850;cause=%i", ast_channel_hangupcause(session->channel) & 0x7f);
128 ast_sip_add_header(tdata, "Reason", buf);
129 }
130}
131
132static void rfc3326_outgoing_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
133{
134 if ((pjsip_method_cmp(&tdata->msg->line.req.method, &pjsip_bye_method)
135 && pjsip_method_cmp(&tdata->msg->line.req.method, &pjsip_cancel_method))
136 || !session->channel
137 /*
138 * The session->channel has been seen to go away on us between
139 * checks so we must also be running under the call's serializer
140 * thread.
141 */
143 return;
144 }
145
147}
148
149static void rfc3326_outgoing_response(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
150{
151 struct pjsip_status_line status = tdata->msg->line.status;
152
153 if (status.code < 300
154 || !session->channel
156 return;
157 }
158
160}
161
164 .incoming_response = rfc3326_incoming_response,
165 .outgoing_request = rfc3326_outgoing_request,
166 .outgoing_response = rfc3326_outgoing_response,
167};
168
174
175static int unload_module(void)
176{
178 return 0;
179}
180
182 .support_level = AST_MODULE_SUPPORT_CORE,
183 .load = load_module,
184 .unload = unload_module,
185 .load_pri = AST_MODPRI_APP_DEPEND,
186 .requires = "res_pjsip,res_pjsip_session",
jack_status_t status
Definition app_jack.c:149
Asterisk main include file. File version handling, generic pbx functions.
static struct ast_mansession session
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition astmm.h:288
Internal Asterisk hangup causes.
#define AST_CAUSE_ANSWERED_ELSEWHERE
Definition causes.h:114
const char * ast_channel_name(const struct ast_channel *chan)
int ast_queue_control_data(struct ast_channel *chan, enum ast_control_frame_type control, const void *data, size_t datalen)
Queue a control frame with payload.
Definition channel.c:1277
int ast_channel_hangupcause(const struct ast_channel *chan)
void ast_channel_hangupcause_hash_set(struct ast_channel *chan, const struct ast_control_pvt_cause_code *cause_code, int datalen)
Sets the HANGUPCAUSE hash and optionally the SIP_CAUSE hash on the given channel.
Definition channel.c:4315
#define AST_CHANNEL_NAME
Definition channel.h:173
const char * ast_cause2str(int cause) attribute_pure
Gives the string form of a given cause code.
Definition channel.c:612
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
char buf[BUFSIZE]
Definition eagi_proxy.c:66
@ AST_CONTROL_PVT_CAUSE_CODE
#define ast_debug(level,...)
Log a DEBUG message.
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition module.h:331
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition module.h:557
@ AST_MODPRI_APP_DEPEND
Definition module.h:342
@ AST_MODULE_SUPPORT_CORE
Definition module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70
const int ast_sip_hangup_sip2cause(int cause)
Convert SIP hangup causes to Asterisk hangup causes.
Definition res_pjsip.c:3531
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
Definition res_pjsip.c:2201
int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
Add a header to an outbound SIP message.
Definition res_pjsip.c:2008
static struct ast_sip_session_supplement rfc3326_supplement
static void rfc3326_add_reason_header(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
static void rfc3326_use_reason_header(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
static int load_module(void)
static int unload_module(void)
static void rfc3326_outgoing_response(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
static void rfc3326_outgoing_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
static void rfc3326_incoming_response(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
static int rfc3326_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
#define ast_sip_session_register_supplement(supplement)
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
Unregister a an supplement to SIP session processing.
#define NULL
Definition resample.c:96
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition sorcery.c:2381
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
char *attribute_pure ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition strings.h:161
A supplement to SIP message processing.
int(* incoming_request)(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
Called on incoming SIP request This method can indicate a failure in processing in its return....
A structure describing a SIP session.
struct header * next
struct ast_taskprocessor * ast_threadpool_serializer_get_current(void)
Get the threadpool serializer currently associated with this thread.