Browse code

core: parser contact - proper update of length in skip_name()

- stop walking name also for unquoted ;, being special char
- small typo

Daniel-Constantin Mierla authored on 07/09/2021 13:36:20
Showing 1 changed files
... ...
@@ -147,10 +147,10 @@ static inline int skip_name(str* _s)
147 147
 					return 0;
148 148
 				}
149 149
 
150
-				if (*p == ':') {
150
+				if (*p == ':' || *p == ';') {
151 151
 					if (last_wsp) {
152
-						_s->s = last_wsp;
153 152
 						_s->len -= last_wsp - _s->s + 1;
153
+						_s->s = last_wsp;
154 154
 					}
155 155
 					return 0;
156 156
 				}
... ...
@@ -224,7 +224,7 @@ int parse_contacts(str* _s, contact_t** _c)
224 224
 
225 225
 		trim(&c->uri);
226 226
 		if((c->uri.len <= 0) || (c->uri.s + c->uri.len > sv.s + sv.len)) {
227
-			LM_ERR("invlid contact uri\n");
227
+			LM_ERR("invalid contact uri\n");
228 228
 			goto error;
229 229
 		}
230 230
 
Browse code

core: parser contact - link structure once finishing current one

Daniel-Constantin Mierla authored on 07/09/2021 08:44:17
Showing 1 changed files
... ...
@@ -262,13 +262,14 @@ int parse_contacts(str* _s, contact_t** _c)
262 262
 		_s->len--;
263 263
 		trim_leading(_s);
264 264
 
265
+		c->next = *_c;
266
+		*_c = c;
267
+		c = NULL;
268
+
265 269
 		if (_s->len == 0) {
266 270
 			LM_ERR("text after comma missing\n");
267 271
 			goto error;
268 272
 		}
269
-
270
-		c->next = *_c;
271
-		*_c = c;
272 273
 	}
273 274
 
274 275
 error:
Browse code

core: parse - validity check for contact uri size and more verbose log message

Daniel-Constantin Mierla authored on 11/04/2019 07:37:25
Showing 1 changed files
... ...
@@ -182,6 +182,9 @@ int parse_contacts(str* _s, contact_t** _c)
182 182
 {
183 183
 	contact_t* c;
184 184
 	param_hooks_t hooks;
185
+	str sv;
186
+
187
+	sv = *_s;
185 188
 
186 189
 	while(1) {
187 190
 		/* Allocate and clear contact structure */
... ...
@@ -220,6 +223,10 @@ int parse_contacts(str* _s, contact_t** _c)
220 223
 		}
221 224
 
222 225
 		trim(&c->uri);
226
+		if((c->uri.len <= 0) || (c->uri.s + c->uri.len > sv.s + sv.len)) {
227
+			LM_ERR("invlid contact uri\n");
228
+			goto error;
229
+		}
223 230
 
224 231
 		if (_s->len == 0) goto ok;
225 232
 
... ...
@@ -265,6 +272,8 @@ int parse_contacts(str* _s, contact_t** _c)
265 272
 	}
266 273
 
267 274
 error:
275
+	LM_ERR("failure parsing '%.*s' (%d) [%p/%p/%d]\n", sv.len, sv.s, sv.len,
276
+			sv.s, _s->s, (int)(_s->s - sv.s));
268 277
 	if (c) pkg_free(c);
269 278
 	free_contacts(_c); /* Free any contacts created so far */
270 279
 	return -1;
Browse code

core/parser: Add parser for 'flags' param in Contact header

Alex Hermann authored on 31/01/2019 16:28:33 • Henning Westerholt committed on 11/02/2019 20:42:26
Showing 1 changed files
... ...
@@ -244,6 +244,7 @@ int parse_contacts(str* _s, contact_t** _c)
244 244
 			c->methods = hooks.contact.methods;
245 245
 			c->instance = hooks.contact.instance;
246 246
 			c->reg_id = hooks.contact.reg_id;
247
+			c->flags = hooks.contact.flags;
247 248
 
248 249
 			if (_s->len == 0) goto ok;
249 250
 		}
... ...
@@ -314,6 +315,7 @@ void print_contacts(FILE* _o, contact_t* _c)
314 315
 		fprintf(_o, "methods : %p\n", ptr->methods);
315 316
 		fprintf(_o, "instance: %p\n", ptr->instance);
316 317
 		fprintf(_o, "reg-id  : %p\n", ptr->reg_id);
318
+		fprintf(_o, "flags   : %p\n", ptr->flags);
317 319
 		fprintf(_o, "len     : %d\n", ptr->len);
318 320
 		if (ptr->params) {
319 321
 			print_params(_o, ptr->params);
Browse code

core: use generic PKG_MEM_ERROR, SHM_ERROR and _CRITICAL helper defines in core

- refactoring of the core to use generic PKG_MEM_ERROR, SHM_ERROR,
PKG_MEM_CRITICAL, SHM_MEM_CRITICAL and SYS_MEM_ERROR helper defines
- unify many different error messages in different spellings
- add a few missing error handler for allocation errors after (found
with a complete review of all memory allocation functions in core)
- no other functional changes, change has been reviewed two times

Henning Westerholt authored on 23/12/2018 21:31:03
Showing 1 changed files
... ...
@@ -187,7 +187,7 @@ int parse_contacts(str* _s, contact_t** _c)
187 187
 		/* Allocate and clear contact structure */
188 188
 		c = (contact_t*)pkg_malloc(sizeof(contact_t));
189 189
 		if (c == 0) {
190
-			LM_ERR("no memory left\n");
190
+			PKG_MEM_ERROR;
191 191
 			goto error;
192 192
 		}
193 193
 		memset(c, 0, sizeof(contact_t));
Browse code

core: parser contact - removed history, updated log macros

- coherent indentation

Daniel-Constantin Mierla authored on 21/08/2017 05:43:44
Showing 1 changed files
... ...
@@ -20,13 +20,10 @@
20 20
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 21
  * GNU General Public License for more details.
22 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 
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 25
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
26 26
  *
27
- * History:
28
- * -------
29
- *  2003-03-25 Adapted to use new parameter parser (janakj)
30 27
  */
31 28
 
32 29
 #include <string.h>        /* memset */
... ...
@@ -54,55 +51,55 @@ static inline int skip_uri(str* _s)
54 51
 
55 52
 	while(_s->len) {
56 53
 		switch(*(_s->s)) {
57
-		case ',':
58
-		case ';':
59
-			if (st == ST1) return 0;
60
-			break;
61
-
62
-		case '\"':
63
-			switch(st) {
64
-			case ST1: st = ST2; break;
65
-			case ST2: st = ST1; break;
66
-			case ST3: st = ST4; break;
67
-			case ST4: st = ST3; break;
68
-			case ST5: st = ST2; break;
69
-			case ST6: st = ST4; break;
70
-			}
71
-			break;
72
-
73
-		case '<':
74
-			switch(st) {
75
-			case ST1: st = ST3; break;
76
-			case ST3: 
77
-				LOG(L_ERR, "skip_uri(): Second < found\n");
78
-				return -1;
79
-			case ST5: st = ST2; break;
80
-			case ST6: st = ST4; break;
81
-			}
82
-			break;
83
-			
84
-		case '>':
85
-			switch(st) {
86
-			case ST1: 
87
-				LOG(L_ERR, "skip_uri(): > is first\n");
88
-				return -2;
89
-
90
-			case ST3: st = ST1; break;
91
-			case ST5: st = ST2; break;
92
-			case ST6: st = ST4; break;
93
-			}
94
-			break;
95
-
96
-		case '\\':
97
-			switch(st) {
98
-			case ST2: st = ST5; break;
99
-			case ST4: st = ST6; break;
100
-			case ST5: st = ST2; break;
101
-			case ST6: st = ST4; break;
102
-			}
103
-			break;
54
+			case ',':
55
+			case ';':
56
+				if (st == ST1) return 0;
57
+				break;
58
+
59
+			case '\"':
60
+				switch(st) {
61
+					case ST1: st = ST2; break;
62
+					case ST2: st = ST1; break;
63
+					case ST3: st = ST4; break;
64
+					case ST4: st = ST3; break;
65
+					case ST5: st = ST2; break;
66
+					case ST6: st = ST4; break;
67
+				}
68
+				break;
69
+
70
+			case '<':
71
+				switch(st) {
72
+					case ST1: st = ST3; break;
73
+					case ST3:
74
+							  LM_ERR("second bracket < found\n");
75
+							  return -1;
76
+					case ST5: st = ST2; break;
77
+					case ST6: st = ST4; break;
78
+				}
79
+				break;
80
+
81
+			case '>':
82
+				switch(st) {
83
+					case ST1:
84
+						LM_ERR("bracket > is first\n");
85
+						return -2;
104 86
 
105
-		default: break;
87
+					case ST3: st = ST1; break;
88
+					case ST5: st = ST2; break;
89
+					case ST6: st = ST4; break;
90
+				}
91
+				break;
92
+
93
+			case '\\':
94
+				switch(st) {
95
+					case ST2: st = ST5; break;
96
+					case ST4: st = ST6; break;
97
+					case ST5: st = ST2; break;
98
+					case ST6: st = ST4; break;
99
+				}
100
+				break;
101
+
102
+			default: break;
106 103
 
107 104
 		}
108 105
 
... ...
@@ -111,7 +108,7 @@ static inline int skip_uri(str* _s)
111 108
 	}
112 109
 
113 110
 	if (st != ST1) {
114
-		LOG(L_ERR, "skip_uri(): < or \" not closed\n");
111
+		LM_ERR("bracket < or \" not closed\n");
115 112
 		return -3;
116 113
 	}
117 114
 
... ...
@@ -129,10 +126,9 @@ static inline int skip_name(str* _s)
129 126
 {
130 127
 	char* last_wsp, *p;
131 128
 	int i, quoted = 0;
132
-	
133 129
 
134 130
 	if (!_s) {
135
-		LOG(L_ERR, "skip_name(): Invalid parameter value\n");
131
+		LM_ERR("invalid parameter value\n");
136 132
 		return -1;
137 133
 	}
138 134
 
... ...
@@ -150,7 +146,7 @@ static inline int skip_name(str* _s)
150 146
 					_s->len -= i;
151 147
 					return 0;
152 148
 				}
153
-				
149
+
154 150
 				if (*p == ':') {
155 151
 					if (last_wsp) {
156 152
 						_s->s = last_wsp;
... ...
@@ -170,9 +166,9 @@ static inline int skip_name(str* _s)
170 166
 	}
171 167
 
172 168
 	if (quoted) {
173
-		LOG(L_ERR, "skip_name(): Closing quote missing in name part of Contact\n");
169
+		LM_ERR("closing quote missing in name part of Contact\n");
174 170
 	} else {
175
-		LOG(L_ERR, "skip_name(): Error in contact, scheme separator not found\n");
171
+		LM_ERR("error in contact, scheme separator not found\n");
176 172
 	}
177 173
 
178 174
 	return -1;
... ...
@@ -188,56 +184,57 @@ int parse_contacts(str* _s, contact_t** _c)
188 184
 	param_hooks_t hooks;
189 185
 
190 186
 	while(1) {
191
-		     /* Allocate and clear contact structure */
187
+		/* Allocate and clear contact structure */
192 188
 		c = (contact_t*)pkg_malloc(sizeof(contact_t));
193 189
 		if (c == 0) {
194
-			LOG(L_ERR, "parse_contacts(): No memory left\n");
190
+			LM_ERR("no memory left\n");
195 191
 			goto error;
196 192
 		}
197 193
 		memset(c, 0, sizeof(contact_t));
198
-		
194
+
199 195
 		c->name.s = _s->s;
200 196
 
201 197
 		if (skip_name(_s) < 0) {
202
-			LOG(L_ERR, "parse_contacts(): Error while skipping name part\n");
198
+			LM_ERR("error while skipping name part\n");
203 199
 			goto error;
204 200
 		}
205 201
 
206 202
 		c->uri.s = _s->s;
207 203
 		c->name.len = _s->s - c->name.s;
208 204
 		trim_trailing(&c->name);
209
-		
210
-		     /* Find the end of the URI */
205
+
206
+		/* Find the end of the URI */
211 207
 		if (skip_uri(_s) < 0) {
212
-			LOG(L_ERR, "parse_contacts(): Error while skipping URI\n");
208
+			LM_ERR("error while skipping URI\n");
213 209
 			goto error;
214 210
 		}
215
-		
211
+
216 212
 		c->uri.len = _s->s - c->uri.s; /* Calculate URI length */
217 213
 		trim_trailing(&(c->uri));      /* Remove any trailing spaces from URI */
218 214
 
219
-		     /* Remove <> if any */
220
-		if ((c->uri.len >= 2) && (c->uri.s[0] == '<') && (c->uri.s[c->uri.len - 1] == '>')) {
215
+		/* Remove <> if any */
216
+		if ((c->uri.len >= 2) && (c->uri.s[0] == '<')
217
+				&& (c->uri.s[c->uri.len - 1] == '>')) {
221 218
 			c->uri.s++;
222 219
 			c->uri.len -= 2;
223 220
 		}
224 221
 
225 222
 		trim(&c->uri);
226
-		
223
+
227 224
 		if (_s->len == 0) goto ok;
228
-		
225
+
229 226
 		if (_s->s[0] == ';') {         /* Contact parameter found */
230 227
 			_s->s++;
231 228
 			_s->len--;
232 229
 			trim_leading(_s);
233
-			
230
+
234 231
 			if (_s->len == 0) {
235
-				LOG(L_ERR, "parse_contacts(): Error while parsing params\n");
232
+				LM_ERR("error while parsing params\n");
236 233
 				goto error;
237 234
 			}
238 235
 
239 236
 			if (parse_params(_s, CLASS_CONTACT, &hooks, &c->params) < 0) {
240
-				LOG(L_ERR, "parse_contacts(): Error while parsing parameters\n");
237
+				LM_ERR("error while parsing parameters\n");
241 238
 				goto error;
242 239
 			}
243 240
 
... ...
@@ -251,14 +248,14 @@ int parse_contacts(str* _s, contact_t** _c)
251 248
 			if (_s->len == 0) goto ok;
252 249
 		}
253 250
 
254
-		     /* Next character is comma */
251
+		/* Next character is comma */
255 252
 		c->len = _s->s - c->name.s;
256 253
 		_s->s++;
257 254
 		_s->len--;
258 255
 		trim_leading(_s);
259 256
 
260 257
 		if (_s->len == 0) {
261
-			LOG(L_ERR, "parse_contacts(): Text after comma missing\n");
258
+			LM_ERR("text after comma missing\n");
262 259
 			goto error;
263 260
 		}
264 261
 
... ...
@@ -266,12 +263,12 @@ int parse_contacts(str* _s, contact_t** _c)
266 263
 		*_c = c;
267 264
 	}
268 265
 
269
- error:
266
+error:
270 267
 	if (c) pkg_free(c);
271 268
 	free_contacts(_c); /* Free any contacts created so far */
272 269
 	return -1;
273 270
 
274
- ok:
271
+ok:
275 272
 	c->len = _s->s - c->name.s;
276 273
 	c->next = *_c;
277 274
 	*_c = c;
Browse code

core, lib, modules: restructured source code tree

- new folder src/ to hold the source code for main project applications
- main.c is in src/
- all core files are subfolder are in src/core/
- modules are in src/modules/
- libs are in src/lib/
- application Makefiles are in src/
- application binary is built in src/ (src/kamailio)

Daniel-Constantin Mierla authored on 07/12/2016 11:03:51
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,327 @@
1
+/*
2
+ * Parses one Contact in Contact HF body
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
+ * History:
28
+ * -------
29
+ *  2003-03-25 Adapted to use new parameter parser (janakj)
30
+ */
31
+
32
+#include <string.h>        /* memset */
33
+#include "../../mem/mem.h" /* pkg_malloc, pkg_free */
34
+#include "../../dprint.h"
35
+#include "../../trim.h"    /* trim_leading, trim_trailing */
36
+#include "contact.h"
37
+
38
+
39
+#define ST1 1 /* Basic state */
40
+#define ST2 2 /* Quoted */
41
+#define ST3 3 /* Angle quoted */
42
+#define ST4 4 /* Angle quoted and quoted */
43
+#define ST5 5 /* Escape in quoted */
44
+#define ST6 6 /* Escape in angle quoted and quoted */
45
+
46
+
47
+/*
48
+ * Skip URI, stops when , (next contact)
49
+ * or ; (parameter) is found
50
+ */
51
+static inline int skip_uri(str* _s)
52
+{
53
+	register int st = ST1;
54
+
55
+	while(_s->len) {
56
+		switch(*(_s->s)) {
57
+		case ',':
58
+		case ';':
59
+			if (st == ST1) return 0;
60
+			break;
61
+
62
+		case '\"':
63
+			switch(st) {
64
+			case ST1: st = ST2; break;
65
+			case ST2: st = ST1; break;
66
+			case ST3: st = ST4; break;
67
+			case ST4: st = ST3; break;
68
+			case ST5: st = ST2; break;
69
+			case ST6: st = ST4; break;
70
+			}
71
+			break;
72
+
73
+		case '<':
74
+			switch(st) {
75
+			case ST1: st = ST3; break;
76
+			case ST3: 
77
+				LOG(L_ERR, "skip_uri(): Second < found\n");
78
+				return -1;
79
+			case ST5: st = ST2; break;
80
+			case ST6: st = ST4; break;
81
+			}
82
+			break;
83
+			
84
+		case '>':
85
+			switch(st) {
86
+			case ST1: 
87
+				LOG(L_ERR, "skip_uri(): > is first\n");
88
+				return -2;
89
+
90
+			case ST3: st = ST1; break;
91
+			case ST5: st = ST2; break;
92
+			case ST6: st = ST4; break;
93
+			}
94
+			break;
95
+
96
+		case '\\':
97
+			switch(st) {
98
+			case ST2: st = ST5; break;
99
+			case ST4: st = ST6; break;
100
+			case ST5: st = ST2; break;
101
+			case ST6: st = ST4; break;
102
+			}
103
+			break;
104
+
105
+		default: break;
106
+
107
+		}
108
+
109
+		_s->s++;
110
+		_s->len--;
111
+	}
112
+
113
+	if (st != ST1) {
114
+		LOG(L_ERR, "skip_uri(): < or \" not closed\n");
115
+		return -3;
116
+	}
117
+
118
+	return 0;
119
+}
120
+
121
+
122
+/*
123
+ * Skip name part
124
+ *
125
+ * _s will be adjusted to point at the beginning
126
+ * of URI
127
+ */
128
+static inline int skip_name(str* _s)
129
+{
130
+	char* last_wsp, *p;
131
+	int i, quoted = 0;
132
+	
133
+
134
+	if (!_s) {
135
+		LOG(L_ERR, "skip_name(): Invalid parameter value\n");
136
+		return -1;
137
+	}
138
+
139
+	p = _s->s;
140
+
141
+	last_wsp = 0;
142
+
143
+	for(i = 0; i < _s->len; i++) {
144
+		if (!quoted) {
145
+			if ((*p == ' ') || (*p == '\t')) {
146
+				last_wsp = p;
147
+			} else {
148
+				if (*p == '<') {
149
+					_s->s = p;
150
+					_s->len -= i;
151
+					return 0;
152
+				}
153
+				
154
+				if (*p == ':') {
155
+					if (last_wsp) {
156
+						_s->s = last_wsp;
157
+						_s->len -= last_wsp - _s->s + 1;
158
+					}
159
+					return 0;
160
+				}
161
+
162
+				if (*p == '\"') {
163
+					quoted = 1;
164
+				}
165
+			}
166
+		} else {
167
+			if ((*p == '\"') && (*(p-1) != '\\')) quoted = 0;
168
+		}
169
+		p++;
170
+	}
171
+
172
+	if (quoted) {
173
+		LOG(L_ERR, "skip_name(): Closing quote missing in name part of Contact\n");
174
+	} else {
175
+		LOG(L_ERR, "skip_name(): Error in contact, scheme separator not found\n");
176
+	}
177
+
178
+	return -1;
179
+}
180
+
181
+
182
+/*
183
+ * Parse contacts in a Contact HF
184
+ */
185
+int parse_contacts(str* _s, contact_t** _c)
186
+{
187
+	contact_t* c;
188
+	param_hooks_t hooks;
189
+
190
+	while(1) {
191
+		     /* Allocate and clear contact structure */
192
+		c = (contact_t*)pkg_malloc(sizeof(contact_t));
193
+		if (c == 0) {
194
+			LOG(L_ERR, "parse_contacts(): No memory left\n");
195
+			goto error;
196
+		}
197
+		memset(c, 0, sizeof(contact_t));
198
+		
199
+		c->name.s = _s->s;
200
+
201
+		if (skip_name(_s) < 0) {
202
+			LOG(L_ERR, "parse_contacts(): Error while skipping name part\n");
203
+			goto error;
204
+		}
205
+
206
+		c->uri.s = _s->s;
207
+		c->name.len = _s->s - c->name.s;
208
+		trim_trailing(&c->name);
209
+		
210
+		     /* Find the end of the URI */
211
+		if (skip_uri(_s) < 0) {
212
+			LOG(L_ERR, "parse_contacts(): Error while skipping URI\n");
213
+			goto error;
214
+		}
215
+		
216
+		c->uri.len = _s->s - c->uri.s; /* Calculate URI length */
217
+		trim_trailing(&(c->uri));      /* Remove any trailing spaces from URI */
218
+
219
+		     /* Remove <> if any */
220
+		if ((c->uri.len >= 2) && (c->uri.s[0] == '<') && (c->uri.s[c->uri.len - 1] == '>')) {
221
+			c->uri.s++;
222
+			c->uri.len -= 2;
223
+		}
224
+
225
+		trim(&c->uri);
226
+		
227
+		if (_s->len == 0) goto ok;
228
+		
229
+		if (_s->s[0] == ';') {         /* Contact parameter found */
230
+			_s->s++;
231
+			_s->len--;
232
+			trim_leading(_s);
233
+			
234
+			if (_s->len == 0) {
235
+				LOG(L_ERR, "parse_contacts(): Error while parsing params\n");
236
+				goto error;
237
+			}
238
+
239
+			if (parse_params(_s, CLASS_CONTACT, &hooks, &c->params) < 0) {
240
+				LOG(L_ERR, "parse_contacts(): Error while parsing parameters\n");
241
+				goto error;
242
+			}
243
+
244
+			c->q = hooks.contact.q;
245
+			c->expires = hooks.contact.expires;
246
+			c->received = hooks.contact.received;
247
+			c->methods = hooks.contact.methods;
248
+			c->instance = hooks.contact.instance;
249
+			c->reg_id = hooks.contact.reg_id;
250
+
251
+			if (_s->len == 0) goto ok;
252
+		}
253
+
254
+		     /* Next character is comma */
255
+		c->len = _s->s - c->name.s;
256
+		_s->s++;
257
+		_s->len--;
258
+		trim_leading(_s);
259
+
260
+		if (_s->len == 0) {
261
+			LOG(L_ERR, "parse_contacts(): Text after comma missing\n");
262
+			goto error;
263
+		}
264
+
265
+		c->next = *_c;
266
+		*_c = c;
267
+	}
268
+
269
+ error:
270
+	if (c) pkg_free(c);
271
+	free_contacts(_c); /* Free any contacts created so far */
272
+	return -1;
273
+
274
+ ok:
275
+	c->len = _s->s - c->name.s;
276
+	c->next = *_c;
277
+	*_c = c;
278
+	return 0;
279
+}
280
+
281
+
282
+/*
283
+ * Free list of contacts
284
+ * _c is head of the list
285
+ */
286
+void free_contacts(contact_t** _c)
287
+{
288
+	contact_t* ptr;
289
+
290
+	while(*_c) {
291
+		ptr = *_c;
292
+		*_c = (*_c)->next;
293
+		if (ptr->params) {
294
+			free_params(ptr->params);
295
+		}
296
+		pkg_free(ptr);
297
+	}
298
+}
299
+
300
+
301
+/*
302
+ * Print list of contacts, just for debugging
303
+ */
304
+void print_contacts(FILE* _o, contact_t* _c)
305
+{
306
+	contact_t* ptr;
307
+
308
+	ptr = _c;
309
+
310
+	while(ptr) {
311
+		fprintf(_o, "---Contact---\n");
312
+		fprintf(_o, "name    : '%.*s'\n", ptr->name.len, ptr->name.s);
313
+		fprintf(_o, "URI     : '%.*s'\n", ptr->uri.len, ptr->uri.s);
314
+		fprintf(_o, "q       : %p\n", ptr->q);
315
+		fprintf(_o, "expires : %p\n", ptr->expires);
316
+		fprintf(_o, "received: %p\n", ptr->received);
317
+		fprintf(_o, "methods : %p\n", ptr->methods);
318
+		fprintf(_o, "instance: %p\n", ptr->instance);
319
+		fprintf(_o, "reg-id  : %p\n", ptr->reg_id);
320
+		fprintf(_o, "len     : %d\n", ptr->len);
321
+		if (ptr->params) {
322
+			print_params(_o, ptr->params);
323
+		}
324
+		fprintf(_o, "---/Contact---\n");
325
+		ptr = ptr->next;
326
+	}
327
+}