20 #include "asterisk/res_pjsip_session.h"
22 #include "pjsip_session.h"
24 static const pj_str_t reason_hdr_str = {
"Reason", 6};
33 static void return_reason_destructor(
void *obj)
36 SCOPE_ENTER(3,
"Destroying RR");
37 ast_free(rr->protocol);
38 ast_free(rr->response_str);
43 #define RETURN_REASON_DATASTORE_NAME "pjsip_session_return_reason"
45 .
type = RETURN_REASON_DATASTORE_NAME,
46 .destroy = return_reason_destructor,
49 static void reason_header_outgoing_response(
struct ast_sip_session *session,
50 struct pjsip_tx_data *tdata)
53 pjsip_generic_string_hdr *reason_hdr;
55 RAII_VAR(
char *, reason_str, NULL, ast_free);
58 struct pjsip_status_line status = tdata->msg->line.status;
59 const char *tag = ast_sip_session_get_name(session);
60 SCOPE_ENTER(3,
"%s: Response Code: %d\n", tag,
67 if (!((PJSIP_IS_STATUS_IN_CLASS(status.code, 100) && status.code != 100) || status.code == 200)) {
68 SCOPE_EXIT_RTN(
"%s: RC %d not eligible for Reason header\n", tag, status.code);
71 datastore = ast_sip_session_get_datastore(session, RETURN_REASON_DATASTORE_NAME);
73 SCOPE_EXIT_RTN(
"%s: No datastore on session. Nothing to do\n", tag);
77 rc =
ast_asprintf(&reason_str,
"%s; cause=%d; text=\"%s\"",
78 rr->protocol, rr->response_code, rr->response_str);
80 ast_sip_session_remove_datastore(session, RETURN_REASON_DATASTORE_NAME);
81 SCOPE_EXIT_RTN(
"%s: Failed to create reason string\n", tag);
83 reason_val = pj_str(reason_str);
91 if (rr->already_sent) {
92 ast_trace(3,
"%s: Reason already sent\n", tag);
93 reason_hdr = pjsip_msg_find_hdr_by_name(tdata->msg, &reason_hdr_str, NULL);
95 ast_trace(3,
"%s: Checking old reason: <" PJSTR_PRINTF_SPEC
"> - <" PJSTR_PRINTF_SPEC
"> \n",
97 PJSTR_PRINTF_VAR(reason_hdr->hvalue), PJSTR_PRINTF_VAR(reason_val));
98 if (pj_strcmp(&reason_hdr->hvalue, &reason_val) == 0) {
99 ast_trace(3,
"%s: MATCH. Cleaning up old reason\n", tag);
100 pj_list_erase(reason_hdr);
103 reason_hdr = pjsip_msg_find_hdr_by_name(tdata->msg, &reason_hdr_str, reason_hdr->next);
105 ast_sip_session_remove_datastore(session, RETURN_REASON_DATASTORE_NAME);
106 SCOPE_EXIT_RTN(
"%s: Done\n", tag);
109 reason_hdr = pjsip_generic_string_hdr_create(tdata->pool, &reason_hdr_str, &reason_val);
111 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)reason_hdr);
112 rr->already_sent = 1;
113 ast_trace(1,
"%s: Created reason header: Reason: %s\n",
116 ast_trace(1,
"%s: Failed to create reason header: Reason: %s\n",
120 SCOPE_EXIT_RTN(
"%s: Done\n", tag);
124 const char *protocol,
int code,
const char *text)
128 const char *tag = ast_sip_session_get_name(session);
129 SCOPE_ENTER(4,
"%s: Adding Reason header %s %d %s\n",
130 tag,
S_OR(protocol,
"<missing protocol>"),
131 code,
S_OR(text,
"<missing text>"));
133 if (ast_strlen_zero(protocol) || !text) {
134 SCOPE_EXIT_RTN_VALUE(-1,
"%s: Missing protocol or text\n", tag);
138 SCOPE_EXIT_RTN_VALUE(-1,
"%s: Failed to allocate datastore\n", tag);
140 datastore = ast_sip_session_alloc_datastore(
141 &return_reason_info, return_reason_info.
type);
143 rr->response_code = code;
145 datastore->data = rr;
146 if (ast_sip_session_add_datastore(session, datastore) != 0) {
147 SCOPE_EXIT_RTN_VALUE(-1,
148 "%s: Failed to add datastore to session\n", tag);
151 SCOPE_EXIT_RTN_VALUE(0,
"%s: Done\n", tag);
156 .priority = AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL + 1,
157 .outgoing_response = reason_header_outgoing_response,
160 void pjsip_reason_header_unload(
void)
162 ast_sip_session_unregister_supplement(&reason_header_supplement);
165 void pjsip_reason_header_load(
void)
167 ast_sip_session_register_supplement(&reason_header_supplement);
Asterisk main include file. File version handling, generic pbx functions.
Structure for a data store type.
#define ast_strdup(str)
A wrapper for strdup()
Structure for a data store object.
A structure describing a SIP session.
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
#define ast_calloc(num, len)
A wrapper for calloc()
A supplement to SIP message processing.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.