Asterisk - The Open Source Telephony Project  18.5.0
route.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  * See http://www.asterisk.org for more information about
7  * the Asterisk project. Please do not directly contact
8  * any of the maintainers of this project for assistance;
9  * the project provides a web site, mailing lists and IRC
10  * channels for your use.
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License Version 2. See the LICENSE file
14  * at the top of the source tree.
15  */
16 
17 /*!
18  * \file
19  * \brief sip_route functions
20  */
21 
22 /*** MODULEINFO
23  <support_level>deprecated</support_level>
24  ***/
25 
26 #include "asterisk.h"
27 
28 #include "asterisk/utils.h"
29 
30 #include "include/route.h"
31 #include "include/reqresp_parser.h"
32 
33 /*!
34  * \brief Traverse route hops
35  */
36 #define sip_route_traverse(route,elem) AST_LIST_TRAVERSE(&(route)->list, elem, list)
37 #define sip_route_first(route) AST_LIST_FIRST(&(route)->list)
38 
39 /*!
40  * \brief Structure to save a route hop
41  */
42 struct sip_route_hop {
44  char uri[0];
45 };
46 
47 const char *sip_route_add(struct sip_route *route, const char *uri, size_t len, int inserthead)
48 {
49  struct sip_route_hop *hop;
50 
51  if (!uri || len < 1 || uri[0] == '\0') {
52  return NULL;
53  }
54 
55  /* Expand len to include null terminator */
56  len++;
57 
58  /* ast_calloc is not needed because all fields are initialized in this block */
59  hop = ast_malloc(sizeof(struct sip_route_hop) + len);
60  if (!hop) {
61  return NULL;
62  }
63  ast_copy_string(hop->uri, uri, len);
64 
65  if (inserthead) {
66  AST_LIST_INSERT_HEAD(&route->list, hop, list);
67  route->type = route_invalidated;
68  } else {
69  if (sip_route_empty(route)) {
70  route->type = route_invalidated;
71  }
72  AST_LIST_INSERT_TAIL(&route->list, hop, list);
73  hop->list.next = NULL;
74  }
75 
76  return hop->uri;
77 }
78 
79 void sip_route_process_header(struct sip_route *route, const char *header, int inserthead)
80 {
81  const char *hop;
82  int len = 0;
83  const char *uri;
84 
85  if (!route) {
86  ast_log(LOG_ERROR, "sip_route_process_header requires non-null route");
87  ast_do_crash();
88  return;
89  }
90 
91  while (!get_in_brackets_const(header, &uri, &len)) {
92  header = strchr(header, ',');
93  if (header >= uri && header <= (uri + len)) {
94  /* comma inside brackets */
95  const char *next_br = strchr(header, '<');
96  if (next_br && next_br <= (uri + len)) {
97  header++;
98  continue;
99  }
100  continue;
101  }
102  if ((hop = sip_route_add(route, uri, len, inserthead))) {
103  ast_debug(2, "sip_route_process_header: <%s>\n", hop);
104  }
105  header = strchr(uri + len + 1, ',');
106  if (header == NULL) {
107  /* No more field-values, we're done with this header */
108  break;
109  }
110  /* Advance past comma */
111  header++;
112  }
113 }
114 
115 void sip_route_copy(struct sip_route *dst, const struct sip_route *src)
116 {
117  struct sip_route_hop *hop;
118 
119  /* make sure dst is empty */
120  sip_route_clear(dst);
121 
122  sip_route_traverse(src, hop) {
123  const char *uri = sip_route_add(dst, hop->uri, strlen(hop->uri), 0);
124  if (uri) {
125  ast_debug(2, "sip_route_copy: copied hop: <%s>\n", uri);
126  }
127  }
128 
129  dst->type = src->type;
130 }
131 
132 void sip_route_clear(struct sip_route *route)
133 {
134  struct sip_route_hop *hop;
135 
136  while ((hop = AST_LIST_REMOVE_HEAD(&route->list, list))) {
137  ast_free(hop);
138  }
139 
140  route->type = route_loose;
141 }
142 
143 void sip_route_dump(const struct sip_route *route)
144 {
145  if (sip_route_empty(route)) {
146  ast_verbose("sip_route_dump: no route/path\n");
147  } else {
148  struct sip_route_hop *hop;
149  sip_route_traverse(route, hop) {
150  ast_verbose("sip_route_dump: route/path hop: <%s>\n", hop->uri);
151  }
152  }
153 }
154 
155 struct ast_str *sip_route_list(const struct sip_route *route, int formatcli, int skip)
156 {
157  struct sip_route_hop *hop;
158  const char *comma;
159  struct ast_str *buf;
160  int i = 0 - skip;
161 
162  buf = ast_str_create(64);
163  if (!buf) {
164  return NULL;
165  }
166 
167  comma = formatcli ? ", " : ",";
168 
169  sip_route_traverse(route, hop) {
170  if (i >= 0) {
171  ast_str_append(&buf, 0, "%s<%s>", i ? comma : "", hop->uri);
172  }
173  i++;
174  }
175 
176  if (formatcli && i <= 0) {
177  ast_str_append(&buf, 0, "N/A");
178  }
179 
180  return buf;
181 }
182 
183 int sip_route_is_strict(struct sip_route *route)
184 {
185  if (!route) {
186  return 0;
187  }
188 
189  if (route->type == route_invalidated) {
190  struct sip_route_hop *hop = sip_route_first(route);
191  int ret = hop && (strstr(hop->uri, ";lr") == NULL);
192  route->type = ret ? route_strict : route_loose;
193  return ret;
194  }
195 
196  return (route->type == route_strict) ? 1 : 0;
197 }
198 
199 const char *sip_route_first_uri(const struct sip_route *route)
200 {
201  struct sip_route_hop *hop = sip_route_first(route);
202  return hop ? hop->uri : NULL;
203 }
Asterisk main include file. File version handling, generic pbx functions.
Structure to store route information.
Definition: route.h:47
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
const char * sip_route_first_uri(const struct sip_route *route)
Get the URI of the route&#39;s first hop.
Definition: route.c:199
#define sip_route_traverse(route, elem)
Traverse route hops.
Definition: route.c:36
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
const char * sip_route_add(struct sip_route *route, const char *uri, size_t len, int inserthead)
Add a new hop to the route.
Definition: route.c:47
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2207
sip_route header file
#define NULL
Definition: resample.c:96
#define sip_route_first(route)
Definition: route.c:37
Utility functions.
int get_in_brackets_const(const char *src, const char **start, int *length)
Get text in brackets on a const without copy.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define sip_route_empty(route)
Check if route has no URI&#39;s.
Definition: route.h:118
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
void sip_route_clear(struct sip_route *route)
Free all routes in the list.
Definition: route.c:132
int sip_route_is_strict(struct sip_route *route)
Check if the route is strict.
Definition: route.c:183
Structure to save a route hop.
Definition: route.c:42
sip request response parser header file
#define LOG_ERROR
Definition: logger.h:285
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
void sip_route_dump(const struct sip_route *route)
Verbose dump of all hops for debugging.
Definition: route.c:143
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void sip_route_process_header(struct sip_route *route, const char *header, int inserthead)
Add routes from header.
Definition: route.c:79
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:409
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
void DO_CRASH_NORETURN ast_do_crash(void)
Force a crash if DO_CRASH is defined.
Definition: main/utils.c:2552
#define ast_free(a)
Definition: astmm.h:182
struct ast_str * sip_route_list(const struct sip_route *route, int formatcli, int skip)
Make the comma separated list of route hops.
Definition: route.c:155
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
struct sip_route_hop::@180 list
void sip_route_copy(struct sip_route *dst, const struct sip_route *src)
copy route-set
Definition: route.c:115
enum sip_route_type type
Definition: route.h:49
struct sip_route_hop * next
Definition: route.c:43
struct sip_route::@165 list
char uri[0]
Definition: route.c:44
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620