123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- /*
- * $Id$
- *
- * Copyright (c) 2006 SOMA Networks, Inc. <http://www.somanetworks.com/>
- *
- * This file is part of Kamailio, a free SIP server.
- *
- * Kamailio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version
- *
- * Kamailio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * History:
- * --------
- * 2006-02-17 Initial revision ([email protected])
- */
- /*!
- * \file
- * \brief SST parser
- * \ingroup parser
- */
- #include "parse_sst.h"
- #include "../../error.h"
- #include "../../dprint.h"
- #include "../../mem/mem.h"
- static inline int/*bool*/ is_space( char c ) { return (c == ' ' || c == '\t'); }
- static inline int/*bool*/ is_num( char c ) { return (c >= '0' && c <= '9'); }
- static inline unsigned lower_byte( char b ) { return b | 0x20; }
- static inline unsigned lower_4bytes( unsigned d ) { return d | 0x20202020; }
- static inline unsigned lower_3bytes( unsigned d ) { return d | 0x202020; }
- static inline unsigned read_4bytes( char *val ) {
- return (*(val + 0) + (*(val + 1) << 8)
- + (*(val + 2) << 16) + (*(val + 3) << 24));
- }
- static inline unsigned read_3bytes( char *val ) {
- return (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16));
- }
- /* compile-time constants if called with constants */
- #define MAKE_4BYTES( a, b, c, d ) \
- ( ((a)&0xFF) | (((b)&0xFF)<<8) | (((c)&0xFF)<<16) | (((d)&0xFF)<<24) )
- #define MAKE_3BYTES( a, b, c ) \
- ( ((a)&0xFF) | (((b)&0xFF)<<8) | (((c)&0xFF)<<16) )
- struct session_expires *
- malloc_session_expires( void )
- {
- struct session_expires *se = (struct session_expires *)
- pkg_malloc( sizeof(struct session_expires) );
- if ( se )
- memset( se, 0, sizeof(struct session_expires) );
- return se;
- }
- /**
- * wrapper to free the content of parsed session-expires header
- */
- void hf_free_session_expires(void *parsed)
- {
- struct session_expires *se;
- se = (struct session_expires*)parsed;
- free_session_expires(se);
- }
- void
- free_session_expires( struct session_expires *se )
- {
- if ( se )
- pkg_free( se );
- }
- enum parse_sst_result
- parse_session_expires_body( struct hdr_field *hf )
- {
- register char *p = hf->body.s;
- int pos = 0;
- int len = hf->body.len;
- char *q;
- struct session_expires se = { 0, 0, sst_refresher_unspecified };
- unsigned tok;
- if ( !p || len <= 0 ) {
- LM_ERR(" no body for header field\n" );
- return parse_sst_header_not_found;
- }
- /* skip whitespace */
- for ( ; pos < len && is_space(*p); ++pos, ++p )
- /*nothing*/;
- /* collect a number */
- for ( q = p; pos < len && is_num(*q); ++pos, ++q )
- se.interval = se.interval*10/*radix*/ + (*q - '0');
- if ( q == p ) /*nothing parsed */ {
- LM_ERR(" no expiry interval\n" );
- return parse_sst_no_value;
- }
- p = q;
- /* continue on with params */
- while ( pos < len ) {
- if ( *p == ';' ) {
- ++p; ++pos;
- if ( pos + 4 < len ) {
- switch ( lower_4bytes(read_4bytes(p)) ) {
- case /*refr*/MAKE_4BYTES('r','e','f','r'):
- if ( pos + 9 <= len
- && lower_4bytes(read_4bytes(p+4))
- == /*eshe*/MAKE_4BYTES('e','s','h','e')
- && lower_byte(*(p+8)) == 'r'
- && *(p+9) == '=' ) {
- tok = lower_3bytes( read_3bytes(p+10) );
- if ( tok == MAKE_3BYTES('u','a','c') ) {
- se.refresher = sst_refresher_uac;
- p += 13; pos += 13;
- }
- else if ( tok == MAKE_3BYTES('u','a','s') ) {
- se.refresher = sst_refresher_uas;
- p += 13; pos += 13;
- }
- else /* unrecognized refresher-param */ {
- LM_ERR(" unrecognized refresher\n" );
- return parse_sst_parse_error;
- }
- }
- else /* not "esher=" */ {
- /* there are no other se-params
- that start with "refr" */
- for ( ; pos < len && *p != ';'; ++pos, ++p )
- /*skip to ';'*/;
- }
- break;
- default:
- /* unrecognized se-param */
- for ( ; pos < len && *p != ';'; ++pos, ++p )
- /*skip to ';'*/;
- break;
- } /*switch*/
- } /* exist 4 bytes to check */
- else /* less than 4 bytes left */ {
- /* not enough text left for any of the recognized se-params */
- /* no other recognized se-param */
- for ( ; pos < len && *p != ';'; ++pos, ++p ) /*skip to ';'*/;
- }
- }
- else /* not ';' */ {
- LM_ERR("no semicolon separating se-params\n");
- return parse_sst_parse_error;
- } /* if ';' */
- } /* while */
- hf->parsed = malloc_session_expires();
- if ( !hf->parsed ) {
- LM_ERR(" out of pkg memory\n" );
- return parse_sst_out_of_mem;
- }
- se.hfree = hf_free_session_expires;
- *((struct session_expires *)hf->parsed) = se;
- return parse_sst_success;
- }
- enum parse_sst_result
- parse_session_expires( struct sip_msg *msg, struct session_expires *se )
- {
- enum parse_sst_result result;
- if ( msg->session_expires ) {
- if ( msg->session_expires->parsed == 0
- && (result = parse_session_expires_body(msg->session_expires))
- != parse_sst_success ) {
- return result;
- }
- if ( se ) {
- *se = *((struct session_expires *)msg->session_expires->parsed);
- }
- return parse_sst_success;
- }
- else {
- return parse_sst_header_not_found;
- }
- }
- enum parse_sst_result
- parse_min_se_body( struct hdr_field *hf )
- {
- int len = hf->body.len;
- char *p = hf->body.s;
- int pos = 0;
- unsigned int interval = 0;
- /* skip whitespace */
- for ( ; pos < len && is_space(*p); ++pos, ++p )
- /*nothing*/;
- if ( pos == len )
- return parse_sst_no_value;
- /* collect a number */
- for ( ; pos < len && is_num(*p); ++pos, ++p )
- interval = interval*10/*radix*/ + (*p - '0');
- /* skip whitespace */
- for ( ; pos < len && is_space(*p); ++pos, ++p )
- /*nothing*/;
- if ( pos != len ) /* shouldn't be any more junk */
- return parse_sst_parse_error;
- hf->parsed=(void*)(long)interval;
- return parse_sst_success;
- }
- enum parse_sst_result
- parse_min_se( struct sip_msg *msg, unsigned int *min_se )
- {
- enum parse_sst_result result;
- if ( msg->min_se ) {
- if ( msg->min_se->parsed == 0
- && (result = parse_min_se_body(msg->min_se))
- != parse_sst_success ) {
- return result;
- }
- if ( min_se ) {
- *min_se = (unsigned int)(long)msg->min_se->parsed;
- }
- return parse_sst_success;
- }
- else {
- return parse_sst_header_not_found;
- }
- }
|