2
0
Эх сурвалжийг харах

added Subscription-State header field parsing (only needed parts)

Vaclav Kubart 19 жил өмнө
parent
commit
488624056c

+ 6 - 0
modules/tm/sip_msg.c

@@ -379,6 +379,7 @@ struct sip_msg*  sip_msg_cloner( struct sip_msg *org_msg, int *sip_msg_len )
 		case HDR_SIPIFMATCH_T:
 		case HDR_SESSIONEXPIRES_T:
 		case HDR_MIN_SE_T:
+		case HDR_SUBSCRIPTION_STATE_T:
 		case HDR_ACCEPTCONTACT_T:
 		case HDR_ALLOWEVENTS_T:
 		case HDR_CONTENTENCODING_T:
@@ -759,6 +760,11 @@ do { \
 				new_msg->min_se = new_hdr;
 			}
 			break;
+		case HDR_SUBSCRIPTION_STATE_T:
+			if (!HOOK_SET(subscription_state)) {
+				new_msg->subscription_state = new_hdr;
+			}
+			break;
 		case HDR_SIPIFMATCH_T:
 			if (!HOOK_SET(sipifmatch)) {
 				new_msg->sipifmatch = new_hdr;

+ 77 - 0
parser/case_subs.h

@@ -0,0 +1,77 @@
+/* 
+ * $Id$ 
+ *
+ * Subject Header Field Name Parsing Macros
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser 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
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    [email protected]
+ *
+ * ser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef CASE_SUBS_H
+#define CASE_SUBS_H
+
+#define te_CASE                         \
+        if (LOWER_BYTE(*p) == 't') { \
+			p++;                   \
+            if (LOWER_BYTE(*p) == 'e') { \
+				p++;               \
+				hdr->type = HDR_SUBSCRIPTION_STATE_T;    \
+		        goto dc_end;       \
+			}                      \
+        }
+
+#define _sta_CASE                         \
+        switch(LOWER_DWORD(val)) { \
+        case __sta_:               \
+	        p += 4;            \
+			te_CASE;         \
+	        goto other;        \
+        }
+
+#define cription_CASE                         \
+        switch(LOWER_DWORD(val)) { \
+        case _tion_:               \
+	        p += 4;            \
+	        val = READ(p);     \
+			_sta_CASE;         \
+	        goto other;        \
+        }
+
+#define crip_CASE                         \
+        switch(LOWER_DWORD(val)) { \
+        case _crip_:               \
+	        p += 4;            \
+	        val = READ(p);     \
+			cription_CASE;     \
+	        goto other;        \
+        }
+
+#define subs_CASE        \
+        p += 4;          \
+        val = READ(p);   \
+        crip_CASE;        \
+        goto other;
+
+
+#endif /* CASE_SUBS_H */

+ 5 - 0
parser/hf.c

@@ -44,6 +44,7 @@
 #include "parse_expires.h"
 #include "parse_sipifmatch.h"
 #include "parse_rr.h"
+#include "parse_subscription_state.h"
 #include "contact/parse_contact.h"
 #include "parse_disposition.h"
 #include "../ut.h"
@@ -166,6 +167,10 @@ void clean_hdr_field(struct hdr_field* hf)
 		case HDR_REFER_TO_T:
 			free_to(hf->parsed);
 			break;
+		
+		case HDR_SUBSCRIPTION_STATE_T:
+			free_subscription_state((subscription_state_t**)hf->parsed);
+			break;
 
 		case HDR_SESSIONEXPIRES_T:
 		case HDR_MIN_SE_T:

+ 3 - 0
parser/hf.h

@@ -89,6 +89,7 @@ enum _hdr_types_t {
 	HDR_SIPIFMATCH_T                   /* SIP-If-Match header field */,
 	HDR_SESSIONEXPIRES_T                           /* Session-Expires header */,
 	HDR_MIN_SE_T                                   /* Min-SE */,
+	HDR_SUBSCRIPTION_STATE_T                       /* Subscription-State */,
 	HDR_ACCEPTCONTACT_T                            /* Accept-Contact header */,
 	HDR_ALLOWEVENTS_T                              /* Allow-Events header */,
 	HDR_CONTENTENCODING_T                          /* Content-Encoding header */,
@@ -148,6 +149,7 @@ typedef unsigned long long hdr_flags_t;
 #define HDR_SIPIFMATCH_F			HDR_F_DEF(SIPIFMATCH)
 #define HDR_SESSIONEXPIRES_F			HDR_F_DEF(SESSIONEXPIRES)
 #define HDR_MIN_SE_F				HDR_F_DEF(MIN_SE)
+#define HDR_SUBSCRIPTION_STATE_F	HDR_F_DEF(SUBSCRIPTION_STATE)
 #define HDR_ACCEPTCONTACT_F			HDR_F_DEF(HDR_ACCEPTCONTACT_T)
 #define HDR_ALLOWEVENTS_F			HDR_F_DEF(HDR_ALLOWEVENTS_T)
 #define HDR_CONTENTENCODING_F			HDR_F_DEF(HDR_CONTENTENCODING_T)
@@ -192,6 +194,7 @@ static inline int hdr_allocs_parse(struct hdr_field* hdr)
 		case HDR_DIVERSION_T:
 		case HDR_RPID_T:
 		case HDR_REFER_TO_T:
+		case HDR_SUBSCRIPTION_STATE_T:
 			return 1;
 		default:
 			return 0;

+ 3 - 0
parser/keys.h

@@ -110,6 +110,9 @@
 #define _prio_ 0x6f697270   /* "prio" */
 #define _rity_ 0x79746972   /* "rity" */
 #define _subj_ 0x6a627573   /* "subj" */
+#define _subs_ 0x73627573   /* "subs" */
+#define _crip_ 0x70697263   /* "crip" */
+#define __sta_ 0x6174732d   /* "-sta" */
 #define _ect2_ 0x20746365   /* "ect " */
 #define _ect1_ 0x3a746365   /* "ect:" */
 #define _user_ 0x72657375   /* "user" */

+ 5 - 0
parser/msg_parser.c

@@ -210,6 +210,7 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
 		case HDR_REFER_TO_T:
 		case HDR_SESSIONEXPIRES_T:
 		case HDR_MIN_SE_T:
+		case HDR_SUBSCRIPTION_STATE_T:
 		case HDR_ACCEPTCONTACT_T:
 		case HDR_ALLOWEVENTS_T:
 		case HDR_CONTENTENCODING_T:
@@ -444,6 +445,10 @@ int parse_headers(struct sip_msg* msg, hdr_flags_t flags, int next)
 				if (msg->min_se==0) msg->min_se = hf;
 				msg->parsed_flag|=HDR_MIN_SE_F;
 				break;
+			case HDR_SUBSCRIPTION_STATE_T:
+				if (msg->subscription_state==0) msg->subscription_state = hf;
+				msg->parsed_flag|=HDR_SUBSCRIPTION_STATE_F;
+				break;
 			case HDR_VIA_T:
 				msg->parsed_flag|=HDR_VIA_F;
 				DBG("parse_headers: Via found, flags=%llx\n",

+ 1 - 0
parser/msg_parser.h

@@ -211,6 +211,7 @@ struct sip_msg {
 	struct hdr_field* session_expires;
 	struct hdr_field* min_se;
 	struct hdr_field* sipifmatch;
+	struct hdr_field* subscription_state;
 
 	char* eoh;        /* pointer to the end of header (if found) or null */
 	char* unparsed;   /* here we stopped parsing*/

+ 2 - 0
parser/parse_hname2.c

@@ -89,6 +89,7 @@ static inline char* skip_ws(char* p, unsigned int size)
 #include "case_sess.h"     /* Session-Expires */
 #include "case_reje.h"     /* Reject-Contact */
 #include "case_min.h"      /* Min-SE */
+#include "case_subs.h"     /* Subscription-State */
 
 
 #define READ(val) \
@@ -118,6 +119,7 @@ static inline char* skip_ws(char* p, unsigned int size)
         case _orga_: orga_CASE; \
         case _prio_: prio_CASE; \
         case _subj_: subj_CASE; \
+        case _subs_: subs_CASE; \
         case _user_: user_CASE; \
         case _dive_: dive_CASE; \
         case _remo_: remo_CASE; \

+ 129 - 0
parser/parse_subscription_state.c

@@ -0,0 +1,129 @@
+#include "parse_subscription_state.h"
+#include "../dprint.h"
+#include "../trim.h"
+#include "../mem/mem.h"
+#include "../ut.h"
+#include "parser_f.h"
+#include "parse_param.h"
+#include <string.h>
+
+void free_subscription_state(subscription_state_t**ss)
+{
+	if (ss) {
+		if (*ss) pkg_free(*ss);
+		*ss = 0;
+	}
+}
+
+static inline int str_cmp(const str *a, const str *b)
+{
+	int i;
+	
+	if (a->len != b->len) return 1;
+	
+	for (i = 0; i < a->len; i++) 
+		if (a->s[i] != b->s[i]) return 1;
+	return 0;
+}
+
+int ss_parse(str *src, subscription_state_t *ss)
+{
+	static str active = STR_STATIC_INIT("active");
+	static str pending = STR_STATIC_INIT("pending");
+	static str terminated = STR_STATIC_INIT("terminated");
+	
+	int res = 0;
+	param_hooks_t ph;
+	param_t *params;
+	str s = *src;
+	str state;
+	char *c, *end;
+	
+	/* initialization */
+	ss->expires_set = 0;
+	ss->expires = 0;
+	
+	trim_leading(&s);
+	end = s.s + s.len;
+		
+	state = s;
+	
+	c = find_not_quoted(&s, ';');
+	if (c) {
+		/* first parameter starts after c */
+		state.len = c - state.s;
+		s.len = s.len - (c - s.s) - 1;
+		s.s = c + 1;
+	}
+	else {
+		s.len = 0;
+	}
+
+	/* set state value */
+	if (str_cmp(&state, &active) == 0) {
+		ss->value = ss_active;
+	}
+	else if (str_cmp(&state, &pending) == 0) {
+		ss->value = ss_pending;
+	}
+	else if (str_cmp(&state, &terminated) == 0) {
+		ss->value = ss_terminated;
+	}
+	else { 
+		/* INFO("unknown subscription-State value :%.*s\n",
+					state.len, state.s); */
+		ss->value = ss_extension;
+	}
+
+	/* explore parameters */
+	
+	trim_leading(&s);
+	if (s.len > 0) {
+		params = NULL;
+		if (parse_params(&s, CLASS_CONTACT, &ph, &params) < 0) {
+			ERR("can't parse params\n");
+			res = -1;
+		}
+		else {
+			if (ph.contact.expires) {
+				ss->expires_set = 1;
+				res = str2int(&ph.contact.expires->body, &ss->expires);
+				if (res != 0) 
+					ERR("invalid expires value: \'%.*s\'\n", 
+						ph.contact.expires->body.len,
+						ph.contact.expires->body.s);
+			}
+			if (params) free_params(params);
+		}
+	}
+	/*
+	ss->value = ss_active;
+	ss->expires = 0;*/
+
+
+	return res;
+}
+
+int parse_subscription_state(struct hdr_field *h)
+{
+	subscription_state_t *ss;
+	if (h->parsed) return 0;
+
+	ss = (subscription_state_t*)pkg_malloc(sizeof(*ss));
+	if (!ss) {
+		ERR("No memory left\n");
+		return -1;
+	}
+
+	memset(ss, 0, sizeof(*ss));
+
+	if (ss_parse(&h->body, ss) < 0) {
+		ERR("Can't parse Subscription-State\n");
+		pkg_free(ss);
+		return -2;
+	}
+
+	h->parsed = (void*)ss;
+	
+	return 0;
+}

+ 26 - 0
parser/parse_subscription_state.h

@@ -0,0 +1,26 @@
+#ifndef __PARSE_SUBSCRIPTION_STATE_H
+#define __PARSE_SUBSCRIPTION_STATE_H
+
+#include "hf.h"
+
+typedef enum {
+	ss_active,
+	ss_pending,
+	ss_terminated,
+	ss_extension
+} substate_value_t;
+
+typedef struct _subscription_state_t {
+	substate_value_t value;
+	unsigned int expires;
+	int expires_set; /* expires is valid if nonzero here */
+} subscription_state_t;
+
+/* FIXME: temporary only */
+int ss_parse(str *src, subscription_state_t *ss);
+
+int parse_subscription_state(struct hdr_field *h);
+
+void free_subscription_state(subscription_state_t **ss);
+
+#endif