32 char uri[PJSIP_MAX_URL_SIZE];
41 char uri[PJSIP_MAX_URL_SIZE];
61 const char *initial_uri)
125 "but %s is not in follow_redirect_methods. Not following redirect.\n",
135 "but this method is not supported in follow_redirect_methods. Not following redirect.\n",
143 pjsip_cseq_hdr *cseq;
146 if (!rdata || !rdata->msg_info.msg || rdata->msg_info.msg->type != PJSIP_RESPONSE_MSG) {
150 msg = rdata->msg_info.msg;
151 status_code = msg->line.status.code;
154 if (!PJSIP_IS_STATUS_IN_CLASS(status_code, 300)) {
159 cseq = rdata->msg_info.cseq;
161 ast_log(
LOG_WARNING,
"Received %d redirect for endpoint '%s', but no CSeq header found\n",
179 if (!strcmp(visited->
uri,
uri)) {
215 static const pj_str_t Q_STR = {
"q", 1 };
218 param = pjsip_param_find(&contact->other_param, &Q_STR);
225 if (param->value.slen > 0) {
228 int len = param->value.slen <
sizeof(q_buf) - 1 ? param->value.slen :
sizeof(q_buf) - 1;
229 memcpy(q_buf, param->value.ptr,
len);
234 return q_val < 0.0f ? 1.0f : q_val;
276 pjsip_contact_hdr *contact_hdr;
277 pjsip_uri *contact_uri;
282 while ((contact_hdr = (pjsip_contact_hdr *) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, start))) {
286 start = contact_hdr->
next;
290 ast_log(
LOG_WARNING,
"Redirect: maximum Contact header limit (%d) reached for endpoint '%s'. Ignoring additional contacts\n",
295 if (!contact_hdr->uri) {
299 contact_uri = (pjsip_uri *)pjsip_uri_get_uri(contact_hdr->uri);
302 if (!PJSIP_URI_SCHEME_IS_SIP(contact_uri) && !PJSIP_URI_SCHEME_IS_SIPS(contact_uri)) {
315 len = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, contact_uri,
343 int status_code = rdata->msg_info.msg->line.status.code;
354 ast_log(
LOG_WARNING,
"Redirect hop limit (%d) reached for endpoint '%s'. Not following redirect.\n",
363 if (contact_count == 0) {
364 ast_log(
LOG_WARNING,
"Received %d redirect without valid Contact headers for endpoint '%s'. Cannot follow redirect.\n",
372 ast_log(
LOG_WARNING,
"Redirect: skipping Contact '%s' for endpoint '%s' (would create loop)\n", contact->
uri,
381 if (contact_count == 0) {
382 ast_log(
LOG_WARNING,
"Redirect: all Contact URIs would create loops for endpoint '%s'. Not following redirect.\n",
421 ast_log(
LOG_WARNING,
"Failed to add URI to visited list for endpoint '%s'. Loop detection may be impaired.\n",
436 return state->hop_count;
441 return state->endpoint;
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdup(str)
A wrapper for strdup()
#define ast_calloc(num, len)
A wrapper for calloc()
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_debug(level,...)
Log a DEBUG message.
A set of macros to manage forward-linked lists.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
int ast_sip_should_redirect(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
Check if redirect should be followed based on endpoint configuration.
int ast_sip_redirect_parse_3xx(pjsip_rx_data *rdata, struct ast_sip_redirect_state *state)
Parse a 3xx redirect response and extract contacts.
int ast_sip_redirect_check_loop(const struct ast_sip_redirect_state *state, const char *uri)
Check if a URI would create a redirect loop.
static const struct redirect_method_map redirect_methods[]
static int is_uri_visited(const struct ast_sip_redirect_state *state, const char *uri)
int ast_sip_redirect_get_next_uri(struct ast_sip_redirect_state *state, char **uri_out)
Get the next redirect URI to try.
static void insert_contact_sorted(struct redirect_contact_list *list, struct redirect_contact *new_contact)
struct ast_sip_endpoint * ast_sip_redirect_get_endpoint(const struct ast_sip_redirect_state *state)
Get the endpoint from the redirect state.
static int method_allowed_for_redirect(struct ast_sip_endpoint *endpoint, const pj_str_t *method_name)
static int add_visited_uri(struct ast_sip_redirect_state *state, const char *uri)
static int parse_redirect_contacts(pjsip_rx_data *rdata, struct redirect_contact_list *contacts, const struct ast_sip_redirect_state *state)
int ast_sip_redirect_get_hop_count(const struct ast_sip_redirect_state *state)
Get the current hop count.
static float extract_q_value(const pjsip_contact_hdr *contact)
void ast_sip_redirect_state_destroy(struct ast_sip_redirect_state *state)
Destroy a redirect state and free all resources.
struct ast_sip_redirect_state * ast_sip_redirect_state_create(struct ast_sip_endpoint *endpoint, const char *initial_uri)
Create a new redirect state.
ast_sip_redirect_method
SIP methods that are allowed to follow 3xx redirects.
@ AST_SIP_REDIRECT_METHOD_MESSAGE
float ast_sip_parse_qvalue(const char *q_value)
Parses a string representing a q_value to a float.
#define AST_SIP_MAX_REDIRECT_HOPS
Maximum number of redirect hops allowed.
#define AST_SIP_MAX_REDIRECT_CONTACTS
Maximum number of redirect contacts to process.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
An entity with which Asterisk communicates.
struct ast_flags follow_redirect_methods
Redirect state structure.
struct ast_sip_endpoint * endpoint
struct redirect_contact_list pending_contacts
struct ast_sip_redirect_state::@497 visited_uris
Mapping of SIP method names to their corresponding redirect flags.
enum ast_sip_redirect_method flag
struct visited_uri::@495 list
char uri[PJSIP_MAX_URL_SIZE]
#define ast_test_flag(p, flag)