summaryrefslogtreecommitdiff
path: root/channels/chan_sip.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels/chan_sip.c')
-rw-r--r--channels/chan_sip.c294
1 files changed, 8 insertions, 286 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 884dd7c23..7a7a38b14 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -20343,292 +20343,6 @@ static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req, in
return 0;
}
-/*! \brief helper routine for sip_uri_cmp
- *
- * This takes the parameters from two SIP URIs and determines
- * if the URIs match. The rules for parameters *suck*. Here's a breakdown
- * 1. If a parameter appears in both URIs, then they must have the same value
- * in order for the URIs to match
- * 2. If one URI has a user, maddr, ttl, or method parameter, then the other
- * URI must also have that parameter and must have the same value
- * in order for the URIs to match
- * 3. All other headers appearing in only one URI are not considered when
- * determining if URIs match
- *
- * \param input1 Parameters from URI 1
- * \param input2 Parameters from URI 2
- * \return Return 0 if the URIs' parameters match, 1 if they do not
- */
-static int sip_uri_params_cmp(const char *input1, const char *input2)
-{
- char *params1 = NULL;
- char *params2 = NULL;
- char *pos1;
- char *pos2;
- int zerolength1 = 0;
- int zerolength2 = 0;
- int maddrmatch = 0;
- int ttlmatch = 0;
- int usermatch = 0;
- int methodmatch = 0;
-
- if (ast_strlen_zero(input1)) {
- zerolength1 = 1;
- } else {
- params1 = ast_strdupa(input1);
- }
- if (ast_strlen_zero(input2)) {
- zerolength2 = 1;
- } else {
- params2 = ast_strdupa(input2);
- }
-
- /*Quick optimization. If both params are zero-length, then
- * they match
- */
- if (zerolength1 && zerolength2) {
- return 0;
- }
-
- pos1 = params1;
- while (!ast_strlen_zero(pos1)) {
- char *name1 = pos1;
- char *value1 = strchr(pos1, '=');
- char *semicolon1 = strchr(pos1, ';');
- int matched = 0;
- if (semicolon1) {
- *semicolon1++ = '\0';
- }
- if (!value1) {
- goto fail;
- }
- *value1++ = '\0';
- /* Checkpoint reached. We have the name and value parsed for param1
- * We have to duplicate params2 each time through the second loop
- * or else we can't search and replace the semicolons with \0 each
- * time
- */
- pos2 = ast_strdupa(params2);
- while (!ast_strlen_zero(pos2)) {
- char *name2 = pos2;
- char *value2 = strchr(pos2, '=');
- char *semicolon2 = strchr(pos2, ';');
- if (semicolon2) {
- *semicolon2++ = '\0';
- }
- if (!value2) {
- goto fail;
- }
- *value2++ = '\0';
- if (!strcasecmp(name1, name2)) {
- if (strcasecmp(value1, value2)) {
- goto fail;
- } else {
- matched = 1;
- break;
- }
- }
- pos2 = semicolon2;
- }
- /* Need to see if the parameter we're looking at is one of the 'must-match' parameters */
- if (!strcasecmp(name1, "maddr")) {
- if (matched) {
- maddrmatch = 1;
- } else {
- goto fail;
- }
- } else if (!strcasecmp(name1, "ttl")) {
- if (matched) {
- ttlmatch = 1;
- } else {
- goto fail;
- }
- } else if (!strcasecmp(name1, "user")) {
- if (matched) {
- usermatch = 1;
- } else {
- goto fail;
- }
- } else if (!strcasecmp(name1, "method")) {
- if (matched) {
- methodmatch = 1;
- } else {
- goto fail;
- }
- }
- pos1 = semicolon1;
- }
-
- /* We've made it out of that horrible O(m*n) construct and there are no
- * failures yet. We're not done yet, though, because params2 could have
- * an maddr, ttl, user, or method header and params1 did not.
- */
- pos2 = params2;
- while (!ast_strlen_zero(pos2)) {
- char *name2 = pos2;
- char *value2 = strchr(pos2, '=');
- char *semicolon2 = strchr(pos2, ';');
- if (semicolon2) {
- *semicolon2++ = '\0';
- }
- if (!value2) {
- goto fail;
- }
- *value2++ = '\0';
- if ((!strcasecmp(name2, "maddr") && !maddrmatch) ||
- (!strcasecmp(name2, "ttl") && !ttlmatch) ||
- (!strcasecmp(name2, "user") && !usermatch) ||
- (!strcasecmp(name2, "method") && !methodmatch)) {
- goto fail;
- }
- }
- return 0;
-
-fail:
- return 1;
-}
-
-/*! \brief helper routine for sip_uri_cmp
- *
- * This takes the "headers" from two SIP URIs and determines
- * if the URIs match. The rules for headers is simple. If a header
- * appears in one URI, then it must also appear in the other URI. The
- * order in which the headers appear does not matter.
- *
- * \param input1 Headers from URI 1
- * \param input2 Headers from URI 2
- * \return Return 0 if the URIs' headers match, 1 if they do not
- */
-static int sip_uri_headers_cmp(const char *input1, const char *input2)
-{
- char *headers1 = NULL;
- char *headers2 = NULL;
- int zerolength1 = 0;
- int zerolength2 = 0;
- int different = 0;
- char *header1;
-
- if (ast_strlen_zero(input1)) {
- zerolength1 = 1;
- } else {
- headers1 = ast_strdupa(input1);
- }
-
- if (ast_strlen_zero(input2)) {
- zerolength2 = 1;
- } else {
- headers2 = ast_strdupa(input2);
- }
-
- if ((zerolength1 && !zerolength2) ||
- (zerolength2 && !zerolength1))
- return 1;
-
- if (zerolength1 && zerolength2)
- return 0;
-
- /* At this point, we can definitively state that both inputs are
- * not zero-length. First, one more optimization. If the length
- * of the headers is not equal, then we definitely have no match
- */
- if (strlen(headers1) != strlen(headers2)) {
- return 1;
- }
-
- for (header1 = strsep(&headers1, "&"); header1; header1 = strsep(&headers1, "&")) {
- if (!strcasestr(headers2, header1)) {
- different = 1;
- break;
- }
- }
-
- return different;
-}
-
-static int sip_uri_cmp(const char *input1, const char *input2)
-{
- char *uri1 = ast_strdupa(input1);
- char *uri2 = ast_strdupa(input2);
- char *host1;
- char *host2;
- char *params1;
- char *params2;
- char *headers1;
- char *headers2;
-
- /* Strip off "sip:" from the URI. We know this is present
- * because it was checked back in parse_request()
- */
- strsep(&uri1, ":");
- strsep(&uri2, ":");
-
- if ((host1 = strchr(uri1, '@'))) {
- *host1++ = '\0';
- }
- if ((host2 = strchr(uri2, '@'))) {
- *host2++ = '\0';
- }
-
- /* Check for mismatched username and passwords. This is the
- * only case-sensitive comparison of a SIP URI
- */
- if ((host1 && !host2) ||
- (host2 && !host1) ||
- (host1 && host2 && strcmp(uri1, uri2))) {
- return 1;
- }
-
- if (!host1) {
- host1 = uri1;
- }
- if (!host2) {
- host2 = uri2;
- }
-
- /* Strip off the parameters and headers so we can compare
- * host and port
- */
-
- if ((params1 = strchr(host1, ';'))) {
- *params1++ = '\0';
- }
- if ((params2 = strchr(host2, ';'))) {
- *params2++ = '\0';
- }
-
- /* Headers come after parameters, but there may be headers without
- * parameters, thus the S_OR
- */
- if ((headers1 = strchr(S_OR(params1, host1), '?'))) {
- *headers1++ = '\0';
- }
- if ((headers2 = strchr(S_OR(params2, host2), '?'))) {
- *headers2++ = '\0';
- }
-
- /* Now the host/port are properly isolated. We can get by with a string comparison
- * because the SIP URI checking rules have some interesting exceptions that make
- * this possible. I will note 2 in particular
- * 1. hostnames which resolve to the same IP address as well as a hostname and its
- * IP address are not considered a match with SIP URI's.
- * 2. If one URI specifies a port and the other does not, then the URIs do not match.
- * This includes if one URI explicitly contains port 5060 and the other implies it
- * by not having a port specified.
- */
-
- if (strcasecmp(host1, host2)) {
- return 1;
- }
-
- /* Headers have easier rules to follow, so do those first */
- if (sip_uri_headers_cmp(headers1, headers2)) {
- return 1;
- }
-
- /* And now the parameters. Ugh */
- return sip_uri_params_cmp(params1, params2);
-}
-
/*! \note No channel or pvt locks should be held while calling this function. */
static int do_magic_pickup(struct ast_channel *channel, const char *extension, const char *context)
{
@@ -28322,9 +28036,16 @@ static int load_module(void)
sip_send_all_registers();
sip_send_all_mwi_subscriptions();
initialize_escs();
+
if (sip_epa_register(&cc_epa_static_data)) {
return AST_MODULE_LOAD_DECLINE;
}
+
+ if (sip_reqresp_parser_init() == -1) {
+ ast_log(LOG_ERROR, "Unable to initialize the SIP request and response parser\n");
+ return AST_MODULE_LOAD_DECLINE;
+ }
+
if (can_parse_xml) {
/* SIP CC agents require the ability to parse XML PIDF bodies
* in incoming PUBLISH requests
@@ -28498,6 +28219,7 @@ static int unload_module(void)
ast_cc_monitor_unregister(&sip_cc_monitor_callbacks);
ast_cc_agent_unregister(&sip_cc_agent_callbacks);
+ sip_reqresp_parser_exit();
sip_unregister_tests();
return 0;