1 /*
2 * Contact header field body parser
3 *
4 * Copyright (C) 2001-2003 FhG Fokus
5 *
6 * This file is part of ser, a free SIP server.
7 *
8 * ser is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version
12 *
13 * For a license to use the ser software under conditions
14 * other than those described here, or to purchase support for this
15 * software, please contact iptel.org by e-mail at the following addresses:
16 * info@iptel.org
17 *
18 * ser is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 *
27 */
28
29 #include <string.h> /* memset */
30 #include "../hf.h"
31 #include "../../mem/mem.h" /* pkg_malloc, pkg_free */
32 #include "../../dprint.h"
33 #include "../../trim.h" /* trim_leading */
34 #include "parse_contact.h"
35
36
37
contact_parser(char * _s,int _l,contact_body_t * _c)38 static inline int contact_parser(char* _s, int _l, contact_body_t* _c)
39 {
40 str tmp;
41
42 tmp.s = _s;
43 tmp.len = _l;
44
45 trim_leading(&tmp);
46
47 if (tmp.len == 0) {
48 LM_ERR("empty body\n");
49 return -1;
50 }
51
52 if (tmp.s[0] == '*') {
53 _c->star = 1;
54 } else {
55 if (parse_contacts(&tmp, &(_c->contacts)) < 0) {
56 LM_ERR("error while parsing contacts\n");
57 return -2;
58 }
59 }
60
61 return 0;
62 }
63
64
65 /*
66 * Parse contact header field body
67 */
parse_contact(struct hdr_field * _h)68 int parse_contact(struct hdr_field* _h)
69 {
70 contact_body_t* b;
71
72 if (_h->parsed != 0) {
73 return 0; /* Already parsed */
74 }
75
76 b = (contact_body_t*)pkg_malloc(sizeof(contact_body_t));
77 if (b == 0) {
78 PKG_MEM_ERROR;
79 return -1;
80 }
81
82 memset(b, 0, sizeof(contact_body_t));
83
84 if (contact_parser(_h->body.s, _h->body.len, b) < 0) {
85 LM_ERR("error while parsing\n");
86 pkg_free(b);
87 return -2;
88 }
89
90 _h->parsed = (void*)b;
91 return 0;
92 }
93
94
95 /*
96 * Free all memory
97 */
free_contact(contact_body_t ** _c)98 void free_contact(contact_body_t** _c)
99 {
100 if(*_c==NULL)
101 return;
102 if ((*_c)->contacts) {
103 free_contacts(&((*_c)->contacts));
104 }
105
106 pkg_free(*_c);
107 *_c = 0;
108 }
109
110
111 /*
112 * Print structure, for debugging only
113 */
print_contact(FILE * _o,contact_body_t * _c)114 void print_contact(FILE* _o, contact_body_t* _c)
115 {
116 fprintf(_o, "===Contact body===\n");
117 fprintf(_o, "star: %d\n", _c->star);
118 print_contacts(_o, _c->contacts);
119 fprintf(_o, "===/Contact body===\n");
120 }
121
122
123 /*
124 * Contact header field iterator, returns next contact if any, it doesn't
125 * parse message header if not absolutely necessary
126 */
contact_iterator(contact_t ** c,struct sip_msg * msg,contact_t * prev)127 int contact_iterator(contact_t** c, struct sip_msg* msg, contact_t* prev)
128 {
129 static struct hdr_field* hdr = 0;
130 struct hdr_field* last;
131 contact_body_t* cb;
132
133 if (!msg) {
134 LM_ERR("invalid parameter value\n");
135 return -1;
136 }
137
138 if (!prev) {
139 /* No pointer to previous contact given, find topmost
140 * contact and return pointer to the first contact
141 * inside that header field
142 */
143 hdr = msg->contact;
144 if (!hdr) {
145 if (parse_headers(msg, HDR_CONTACT_F, 0) == -1) {
146 LM_ERR("error while parsing headers\n");
147 return -1;
148 }
149
150 hdr = msg->contact;
151 }
152
153 if (hdr) {
154 if (parse_contact(hdr) < 0) {
155 LM_ERR("error while parsing Contact\n");
156 return -1;
157 }
158 } else {
159 *c = 0;
160 return 1;
161 }
162
163 cb = (contact_body_t*)hdr->parsed;
164 *c = cb->contacts;
165 return 0;
166 } else {
167 /* Check if there is another contact in the
168 * same header field and if so then return it
169 */
170 if (prev->next) {
171 *c = prev->next;
172 return 0;
173 }
174
175 if(hdr==NULL) {
176 LM_ERR("contact iterator not initialized\n");
177 return -1;
178 }
179
180 /* Try to find and parse another Contact
181 * header field
182 */
183 last = hdr;
184 hdr = hdr->next;
185
186 /* Search another already parsed Contact
187 * header field
188 */
189 while(hdr && hdr->type != HDR_CONTACT_T) {
190 hdr = hdr->next;
191 }
192
193 if (!hdr) {
194 /* Look for another Contact HF in unparsed
195 * part of the message header
196 */
197 if (parse_headers(msg, HDR_CONTACT_F, 1) == -1) {
198 LM_ERR("error while parsing message header\n");
199 return -1;
200 }
201
202 /* Check if last found header field is Contact
203 * and if it is not the same header field as the
204 * previous Contact HF (that indicates that the previous
205 * one was the last header field in the header)
206 */
207 if ((msg->last_header->type == HDR_CONTACT_T) &&
208 (msg->last_header != last)) {
209 hdr = msg->last_header;
210 } else {
211 *c = 0;
212 return 1;
213 }
214 }
215
216 if (parse_contact(hdr) < 0) {
217 LM_ERR("error while parsing Contact HF body\n");
218 return -1;
219 }
220
221 /* And return first contact within that
222 * header field
223 */
224 cb = (contact_body_t*)hdr->parsed;
225 *c = cb->contacts;
226 return 0;
227 }
228 }
229