Skip to content

Conversation

@maximilianfridrich
Copy link
Contributor

@maximilianfridrich maximilianfridrich commented Nov 7, 2025

res_pjsip: Introduce redirect module for handling 3xx responses
This commit introduces a new redirect handling module that provides
infrastructure for following SIP 3xx redirect responses. The redirect
functionality respects the endpoint's redirect_method setting and only
follows redirects when set to 'uri_pjsip'. This infrastructure can be
used by any PJSIP module that needs to handle 3xx redirect responses.

res_pjsip_messaging: Add support for following 3xx redirects
This commit integrates the redirect module into res_pjsip_messaging
to enable following 3xx redirect responses for outgoing SIP MESSAGEs.

When redirect_method is set to 'uri_pjsip' on an endpoint, Asterisk
will now follow 3xx redirect responses for MESSAGEs, similar to how
it behaves for INVITE responses. For other redirect_method values (user,
uri_core), redirects are not followed for MESSAGEs, maintaining backward
compatibility.

Resolves: #1576

UserNote: When redirect_method is set to 'uri_pjsip' on a pjsip
endpoint, Asterisk will now follow 3xx redirect responses for MESSAGEs.

@maximilianfridrich
Copy link
Contributor Author

cherry-pick-to: 20
cherry-pick-to: 22
cherry-pick-to: 23
multiple-commits: standalone
testsuite-test-pr: 117

@github-actions
Copy link

github-actions bot commented Nov 7, 2025

Workflow PRCheck completed successfully

@github-actions
Copy link

github-actions bot commented Nov 9, 2025

Workflow PRCheck completed successfully

@github-actions
Copy link

Workflow PRCheck completed successfully

/*!
* \brief Maximum size for a URI string
*/
#define AST_SIP_MAX_URI_SIZE 512
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason not to use the PJSIP defined one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought there was a PJSIP defined one but I couldn't find it. I found it now and will use it. Thanks.

/*!
* \brief Maximum number of redirect hops allowed
*/
#define AST_SIP_MAX_REDIRECT_HOPS 5
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where did 5 come from?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Completely arbitrary. I thought this could be a sensible/safe "maximum".
Would you want it to be configurable, or something else?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it ever became an issue we could make it configurable, same for redirect contacts. Realistically I don't expect this will ever need to change or be touched - but was wondering if there was some source that needed to be documented as where the value came from.

/*!
* \brief Maximum number of redirect contacts to process
*/
#define AST_SIP_MAX_REDIRECT_CONTACTS 20
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where did 20 come from?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Completely arbitrary. I just thought it could be good to have a maximum.

* SIP 3xx redirects, including visited URIs for loop detection,
* pending contacts for retry logic, and hop counting.
*/
struct ast_sip_redirect_context;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Context has a rather specific meaning within Asterisk, and I must admit on reading this name I thought it meant dialplan context and was confused until the brief description sunk in. I think a different name would eliminate that confusion. "ast_sip_redirect_state"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, thanks and sorry about the confusion. I'll rename everything to state.

* \brief Check if redirect should be followed based on endpoint configuration
*
* \param endpoint The SIP endpoint
* \param status_code The response status code
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The response status code from what?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I clarified the doc comment: "The status code from a SIP response message (e.g. 305)"

return 1.0f;
}

/* Parse the q value */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're on our second implementation of this with the other being in security_agreements.c - if possible I think a common parsing function in res_pjsip.c would be good

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, thanks. Sorry about the duplication. I moved the conversion from string to float to res_pjsip.c.

* \param contacts List to populate with parsed contacts
* \return Number of valid contacts found
*/
static int parse_redirect_contacts(pjsip_rx_data *rdata, struct redirect_contact_list *contacts)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass in the state/context pointer, and use the endpoint to add name to the logging

I'm kind of a broken record lately with logging, but giving information on which endpoint is involved can be very valuable if someone goes back to try to understand what happened on a well used system

The same applies for the code going forward after this comment, I'm not going to comment on each one but I urge you to go back to each and try to make them more specific/detailed including endpoint name

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood. I tried to add the endpoint ID to the logs (mostly within the prose). Let me know if this is okay or if you would like it differently (e.g. a consistent format).

return -1;
}

ast_log(LOG_NOTICE, "Redirect: found %d Contact header%s\n", contact_count, contact_count == 1 ? "" : "s");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be removed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Done.

{
struct message_response_data *resp_data;

resp_data = ao2_alloc(sizeof(*resp_data), message_response_data_destroy);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be allocated without a lock using ao2_alloc_options

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Done.

struct msg_data *mdata = data; /* The caller holds a reference */
/* Callback data for redirect handling */
struct message_response_data *resp_data;
char content_type_buf[128];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where did 128 come from?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arbitrary. I thought that should be enough for the Content-Type header which contains a MIME type (potentially with parameters). I changed it now to a malloced ast_str which can grow if needed.

This commit introduces a new redirect handling module that provides
infrastructure for following SIP 3xx redirect responses. The redirect
functionality respects the endpoint's redirect_method setting and only
follows redirects when set to 'uri_pjsip'. This infrastructure can be
used by any PJSIP module that needs to handle 3xx redirect responses.
This commit integrates the redirect module into res_pjsip_messaging
to enable following 3xx redirect responses for outgoing SIP MESSAGEs.

When redirect_method is set to 'uri_pjsip' on an endpoint, Asterisk
will now follow 3xx redirect responses for MESSAGEs, similar to how
it behaves for INVITE responses. For other redirect_method values (user,
uri_core), redirects are not followed for MESSAGEs, maintaining backward
compatibility.

Resolves: asterisk#1576

UserNote: When redirect_method is set to 'uri_pjsip' on a pjsip
endpoint, Asterisk will now follow 3xx redirect responses for MESSAGEs.
@maximilianfridrich
Copy link
Contributor Author

Thanks for the review @jcolp! I've incorporated your feedback and responded to your comments. Let me know what you think.

@github-actions
Copy link

Workflow PRCheck completed successfully

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[improvement]: res_pjsip_messaging: Follow 3xx redirect messages if redirect_method=uri_pjsip

2 participants