Browse code

Adding the sst parser from kamailio core

Jan Janak authored on 29/03/2009 19:49:57
Showing 2 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,241 @@
1
+/*
2
+ * $Id$
3
+ * 
4
+ * Copyright (c) 2006 SOMA Networks, Inc. <http://www.somanetworks.com/>
5
+ *
6
+ * This file is part of Kamailio, a free SIP server.
7
+ *
8
+ * Kamailio 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
+ * Kamailio is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License 
19
+ * along with this program; if not, write to the Free Software 
20
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
+ *
22
+ * History:
23
+ * --------
24
+ * 2006-02-17 Initial revision (dhsueh@somanetworks.com)
25
+ */
26
+
27
+/*!
28
+ * \file
29
+ * \brief SST parser
30
+ * \ingroup parser
31
+ */
32
+
33
+#include "parse_sst.h"
34
+
35
+#include "../error.h"
36
+#include "../dprint.h"
37
+#include "../mem/mem.h"
38
+
39
+
40
+inline int/*bool*/  is_space( char c ) { return (c == ' ' || c == '\t'); }
41
+inline int/*bool*/  is_num( char c ) { return (c >= '0' && c <= '9'); }
42
+
43
+inline unsigned  lower_byte( char b ) { return b | 0x20; }
44
+inline unsigned  lower_4bytes( unsigned d ) { return d | 0x20202020; }
45
+inline unsigned  lower_3bytes( unsigned d ) { return d |   0x202020; }
46
+inline unsigned  read_4bytes( char *val ) {
47
+	return (*(val + 0) + (*(val + 1) << 8)
48
+		+ (*(val + 2) << 16) + (*(val + 3) << 24));
49
+}
50
+inline unsigned  read_3bytes( char *val ) {
51
+	return (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16));
52
+}
53
+
54
+/* compile-time constants if called with constants */
55
+#define  MAKE_4BYTES( a, b, c, d ) \
56
+	( ((a)&0xFF) | (((b)&0xFF)<<8) | (((c)&0xFF)<<16) | (((d)&0xFF)<<24) )
57
+#define  MAKE_3BYTES( a, b, c ) \
58
+	( ((a)&0xFF) | (((b)&0xFF)<<8) | (((c)&0xFF)<<16) )
59
+
60
+
61
+struct session_expires *
62
+malloc_session_expires( void )
63
+{
64
+	struct session_expires *se = (struct session_expires *)
65
+		pkg_malloc( sizeof(struct session_expires) );
66
+	if ( se )
67
+		memset( se, 0, sizeof(struct session_expires) );
68
+	return se;
69
+}
70
+
71
+
72
+void
73
+free_session_expires( struct session_expires *se )
74
+{
75
+	if ( se )
76
+		pkg_free( se );
77
+}
78
+
79
+
80
+enum parse_sst_result
81
+parse_session_expires_body( struct hdr_field *hf )
82
+{
83
+	register char *p = hf->body.s;
84
+	int pos = 0;
85
+	int len = hf->body.len;
86
+	char *q;
87
+	struct session_expires se = { 0, sst_refresher_unspecified };
88
+	unsigned tok;
89
+
90
+	if ( !p || len <= 0 ) {
91
+		LM_ERR(" no body for header field\n" );
92
+		return parse_sst_header_not_found;
93
+	}
94
+
95
+	/* skip whitespace */
96
+	for ( ; pos < len && is_space(*p); ++pos, ++p )
97
+		/*nothing*/;
98
+
99
+	/* collect a number */
100
+	for ( q = p; pos < len && is_num(*q); ++pos, ++q )
101
+		se.interval = se.interval*10/*radix*/ + (*q - '0');
102
+
103
+	if ( q == p ) /*nothing parsed */ {
104
+		LM_ERR(" no expiry interval\n" );
105
+		return parse_sst_no_value;
106
+	}
107
+	p = q;
108
+
109
+	/* continue on with params */
110
+	while ( pos < len ) {
111
+
112
+		if ( *p == ';' ) {
113
+			++p; ++pos;
114
+
115
+			if ( pos + 4 < len ) {
116
+				switch ( lower_4bytes(read_4bytes(p)) ) {
117
+					case /*refr*/MAKE_4BYTES('r','e','f','r'):
118
+						if ( pos + 9 <= len
119
+							 && lower_4bytes(read_4bytes(p+4))
120
+								== /*eshe*/MAKE_4BYTES('e','s','h','e')
121
+							 && lower_byte(*(p+8)) == 'r'
122
+							 && *(p+9) == '=' ) {
123
+							tok = lower_3bytes( read_3bytes(p+10) );
124
+							if ( tok == MAKE_3BYTES('u','a','c') ) {
125
+								se.refresher = sst_refresher_uac;
126
+								p += 13; pos += 13;
127
+							}
128
+							else if ( tok == MAKE_3BYTES('u','a','s') ) {
129
+								se.refresher = sst_refresher_uas;
130
+								p += 13; pos += 13;
131
+							}
132
+							else /* unrecognized refresher-param */ {
133
+								LM_ERR(" unrecognized refresher\n" );
134
+								return parse_sst_parse_error;
135
+							}
136
+						}
137
+						else /* not "esher=" */ {
138
+							/* there are no other se-params 
139
+							   that start with "refr" */
140
+							for ( ; pos < len && *p != ';'; ++pos, ++p )
141
+								/*skip to ';'*/;
142
+						}
143
+						break;
144
+					default:
145
+						/* unrecognized se-param */
146
+						for ( ; pos < len && *p != ';'; ++pos, ++p )
147
+							/*skip to ';'*/;
148
+						break;
149
+				} /*switch*/
150
+			} /* exist 4 bytes to check */
151
+			else /* less than 4 bytes left */ {
152
+				/* not enough text left for any of the recognized se-params */
153
+				/* no other recognized se-param */
154
+				for ( ; pos < len && *p != ';'; ++pos, ++p ) /*skip to ';'*/;
155
+			}
156
+		}
157
+		else /* not ';' */ {
158
+			LM_ERR("no semicolon separating se-params\n");
159
+			return parse_sst_parse_error;
160
+		} /* if ';' */
161
+	} /* while */
162
+
163
+	hf->parsed = malloc_session_expires();
164
+	if ( !hf->parsed ) {
165
+		LM_ERR(" out of pkg memory\n" );
166
+		return parse_sst_out_of_mem;
167
+	}
168
+	*((struct session_expires *)hf->parsed) = se;
169
+
170
+	return parse_sst_success;
171
+}
172
+
173
+
174
+enum parse_sst_result
175
+parse_session_expires( struct sip_msg *msg, struct session_expires *se )
176
+{
177
+	enum parse_sst_result result;
178
+
179
+	if ( msg->session_expires ) {
180
+		if ( msg->session_expires->parsed == 0
181
+			 && (result = parse_session_expires_body(msg->session_expires))
182
+				!= parse_sst_success ) {
183
+			return result;
184
+		}
185
+		if ( se ) {
186
+			*se = *((struct session_expires *)msg->session_expires->parsed);
187
+		}
188
+		return parse_sst_success;
189
+	}
190
+	else {
191
+		return parse_sst_header_not_found;
192
+	}
193
+}
194
+
195
+
196
+enum parse_sst_result
197
+parse_min_se_body( struct hdr_field *hf )
198
+{
199
+	int len = hf->body.len;
200
+	char *p = hf->body.s;
201
+	int pos = 0;
202
+	unsigned int interval = 0;
203
+
204
+	/* skip whitespace */
205
+	for ( ; pos < len && is_space(*p); ++pos, ++p )
206
+		/*nothing*/;
207
+	if ( pos == len )
208
+		return parse_sst_no_value;
209
+	/* collect a number */
210
+	for ( ; pos < len && is_num(*p); ++pos, ++p )
211
+		interval = interval*10/*radix*/ + (*p - '0');
212
+	/* skip whitespace */
213
+	for ( ; pos < len && is_space(*p); ++pos, ++p )
214
+		/*nothing*/;
215
+	if ( pos != len ) /* shouldn't be any more junk */
216
+		return parse_sst_parse_error;
217
+	hf->parsed=(void*)(long)interval;
218
+	return parse_sst_success;
219
+}
220
+
221
+
222
+enum parse_sst_result
223
+parse_min_se( struct sip_msg *msg, unsigned int *min_se )
224
+{
225
+	enum parse_sst_result result;
226
+
227
+	if ( msg->min_se ) {
228
+		if ( msg->min_se->parsed == 0
229
+			 && (result = parse_min_se_body(msg->min_se))
230
+				!= parse_sst_success ) {
231
+			return result;
232
+		}
233
+		if ( min_se ) {
234
+			*min_se = (unsigned int)(long)msg->min_se->parsed;
235
+		}
236
+		return parse_sst_success;
237
+	}
238
+	else {
239
+		return parse_sst_header_not_found;
240
+	}
241
+}
0 242
new file mode 100644
... ...
@@ -0,0 +1,128 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * Copyright (c) 2006 SOMA Networks, Inc. <http://www.somanetworks.com/>
5
+ *
6
+ * This file is part of Kamailio, a free SIP server.
7
+ *
8
+ * Kamailio 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
+ * Kamailio is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License 
19
+ * along with this program; if not, write to the Free Software 
20
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
+ *
22
+ * History:
23
+ * --------
24
+ * 2006-02-17 Initial revision (dhsueh@somanetworks.com)
25
+ */
26
+
27
+/*!
28
+ * \file
29
+ * \brief SST parser
30
+ * \ingroup parser
31
+ */
32
+
33
+#ifndef PARSE_SST_H
34
+#define PARSE_SST_H 1
35
+
36
+
37
+#include "msg_parser.h"
38
+#include "hf.h"
39
+
40
+
41
+/*!
42
+ * Indicate the "refresher=" value of the Session-Expires header.
43
+ */
44
+enum sst_refresher {
45
+	sst_refresher_unspecified,
46
+	sst_refresher_uac,
47
+	sst_refresher_uas,
48
+};
49
+
50
+
51
+/*!
52
+ * We will treat the 'void* parsed' field of struct hdr_field as
53
+ * a pointer to a struct session_expires.
54
+ */
55
+struct session_expires {
56
+	unsigned            interval; /* in seconds */
57
+	enum sst_refresher  refresher;
58
+};
59
+
60
+
61
+enum parse_sst_result {
62
+	parse_sst_success,
63
+	parse_sst_header_not_found,	/* no header */
64
+	parse_sst_no_value,			/* no interval specified */
65
+#if NOT_IMPLEMENTED_YET
66
+	parse_sst_duplicate,		/* multiple s-e / x / min-se headers found */
67
+#endif
68
+	parse_sst_out_of_mem,
69
+	parse_sst_parse_error,		/* something puked */
70
+};
71
+
72
+
73
+/*!
74
+ * Allocate a zeroed-out struct session_expires.
75
+ */
76
+struct session_expires *
77
+malloc_session_expires( void );
78
+
79
+
80
+/*!
81
+ * Deallocates memory previously allocated via malloc_session_expires().
82
+ */
83
+void
84
+free_session_expires( struct session_expires * );
85
+
86
+
87
+/*!
88
+ * \brief Parses the (should be only one instance) single instance of the
89
+ * "Session-Expires" or "x" header in the msg. 
90
+ * \note The header is not automatically parsed in parse_headers()[1]
91
+ * so you'll have to call this function to get the information.
92
+ *
93
+ * Because of time constraints, this function is coded assuming there is
94
+ * NO WHITESPACE in any of the body -- note that the augBNF for the
95
+ * Session-Expires body allows sep whitespace between tokens:
96
+ *   delta-seconds SWS ";" SWS "refresher" SWS "=" SWS ( "uac" / "uas" )
97
+ *
98
+ * Note[1]: it looks like only the frequently-used headers are
99
+ * automatically parsed in parse_headers() (indicated by a parse_<name>
100
+ * function of the form "char* parse_<name>(char *buf, char *end, foo*)
101
+ * and a struct foo with a member called "error").
102
+ *
103
+ * \param msg the sip message to examine
104
+ * \param se the place to store session-expires information into, if
105
+ *         provided; note that result is also available in
106
+ *         *((struct session_expires *)msg->session_expires->parsed)
107
+ * \return parse_sst_result
108
+ */
109
+enum parse_sst_result
110
+parse_session_expires( struct sip_msg *msg, struct session_expires *se );
111
+
112
+
113
+/*!
114
+ * \brief Parses the (should be only one instance) single instance of the
115
+ * "Min-SE" header in the msg. 
116
+ * \note The header is not automatically parsed in parse_headers() so you'll have
117
+ * to call this function to get the information.
118
+ *
119
+ * \param msg the sip message to examine
120
+ * \param min_se the place to store the Min-SE value, if provided; note that
121
+ *         result is also available in (unsigned)msg->min_se->parsed
122
+ * \return parse_sst_result
123
+ */
124
+enum parse_sst_result
125
+parse_min_se( struct sip_msg *msg, unsigned *min_se );
126
+
127
+
128
+#endif /* ! PARSE_SST_H */