[SR-Dev] git:master: Refurbished event header field parser.

Jan Janak jan at iptel.org
Tue Mar 17 17:42:30 CET 2009


Module: sip-router
Branch: master
Commit: 1ee365faf8047d7a921da5a0bf5cc7d20f766a27
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=1ee365faf8047d7a921da5a0bf5cc7d20f766a27

Author: Jan Janak <jan at iptel.org>
Committer: Jan Janak <jan at iptel.org>
Date:   Tue Mar 17 17:41:19 2009 +0100

Refurbished event header field parser.

This is a new refurbished version of the Event header parser which adds
support for extra event packages and parameters needed by kamailio
presence modules, however both the implementation and the parser API
are different. It turned out that the original k. event parser (which
is an extended version of the same parser in ser) did not parse dialog
event packages correctly. The parser relies on the recently added
extensions to the generic parameter parser.

First off, the event structure contains different fields now, field
text has been renamed to name and field parsed has been renamed to type.
In addition that that there is a new structure dialog which contains
the linked list of all parsed parameters in variable list and pointers
to well known dialog event package parameters in structure dialog.

The test for the presence of the sla dialog event parameter would then
look like this:

if (e->type == EVENT_DIALOG && e->params.dialog.sla) ...

Support for new event types can be easily added by extending the global
variable events in parse_event.c, previously it was necessary to modify
the parser function, in the refurbished version it is sufficient just
to add a new element in the array and define a new event type in
parse_event.h

The original k. version handled "dialog;sla" and "dialog" as different
event types. This is no more so, in both cases event->type will be set
to EVENT_DIALOG and the caller can descriminate them by testing for
the presence of the sla parameter as described in the text above.

Function free_event has been modified to free the linked list of parsed
parameters in event->params.list.

---

 parser/parse_event.c |  101 ++++++++++++++++++++++++++++++-------------------
 parser/parse_event.h |   42 +++++++++++++--------
 2 files changed, 88 insertions(+), 55 deletions(-)

diff --git a/parser/parse_event.c b/parser/parse_event.c
index 75b7017..98ca5e5 100644
--- a/parser/parse_event.c
+++ b/parser/parse_event.c
@@ -44,18 +44,19 @@
 #include <stdio.h>         /* printf */
 #include "../ut.h"
 
-
-#define PRES_STR "presence"
-#define PRES_STR_LEN 8
-
-#define PRES_WINFO_STR "presence.winfo"
-#define PRES_WINFO_STR_LEN 14
-
-#define PRES_XCAP_CHANGE_STR "xcap-change"
-#define PRES_XCAP_CHANGE_STR_LEN 11
-
-#define PRES_SIP_PROFILE_STR "sip-profile"
-#define PRES_SIP_PROFILE_STR_LEN 11
+static struct {
+	str name;
+	int type;	
+} events[] = {
+	{STR_STATIC_INIT("presence"),        EVENT_PRESENCE},
+	{STR_STATIC_INIT("presence.winfo"),  EVENT_PRESENCE_WINFO},
+	{STR_STATIC_INIT("xcap-change"),     EVENT_XCAP_CHANGE},
+	{STR_STATIC_INIT("sip-profile"),     EVENT_SIP_PROFILE},
+	{STR_STATIC_INIT("message-summary"), EVENT_MESSAGE_SUMMARY},
+	{STR_STATIC_INIT("dialog"),          EVENT_DIALOG},
+	/* The following must be the last element in the array */
+	{STR_NULL,                           EVENT_OTHER}
+};
 
 
 static inline char* skip_token(char* _b, int _l)
@@ -77,41 +78,58 @@ static inline char* skip_token(char* _b, int _l)
 }
 
 
-static inline int event_parser(char* _s, int _l, event_t* _e)
+int event_parser(char* s, int len, event_t* e)
 {
+	int i;
 	str tmp;
 	char* end;
+	param_hooks_t* phooks = NULL;
+	enum pclass pclass = CLASS_ANY;
 
-	tmp.s = _s;
-	tmp.len = _l;
+	if (e == NULL) {
+		ERR("event_parser: Invalid parameter value\n");
+		return -1;
+	}
 
+	tmp.s = s;
+	tmp.len = len;
 	trim_leading(&tmp);
 
 	if (tmp.len == 0) {
-		LOG(L_ERR, "event_parser(): Empty body\n");
+		LOG(L_ERR, "event_parser: Empty body\n");
 		return -1;
 	}
 
-	_e->text.s = tmp.s;
-
+	e->name.s = tmp.s;
 	end = skip_token(tmp.s, tmp.len);
+	e->name.len = end - tmp.s;
+
+	e->type = EVENT_OTHER;
+	for(i = 0; events[i].name.len; i++) {
+		if (e->name.len == events[i].name.len &&
+			!strncasecmp(e->name.s, events[i].name.s, e->name.len)) {
+			e->type = events[i].type;
+			break;
+		}
+	}
+
+	tmp.len -= end - tmp.s;
+	tmp.s = end;
+	trim_leading(&tmp);
+
+	if (tmp.s[0] == ';') {
+		/* We have parameters to parse */
+		if (e->type == EVENT_DIALOG) {
+			pclass = CLASS_EVENT_DIALOG;
+			phooks = (param_hooks_t*)&e->params.dialog;
+		}
 
-	_e->text.len = end - tmp.s;
-
-	if ((_e->text.len == PRES_STR_LEN) && 
-	    !strncasecmp(PRES_STR, tmp.s, _e->text.len)) {
-		_e->parsed = EVENT_PRESENCE;
-	} else if ((_e->text.len == PRES_XCAP_CHANGE_STR_LEN) && 
-		   !strncasecmp(PRES_XCAP_CHANGE_STR, tmp.s, _e->text.len)) {
-		_e->parsed = EVENT_XCAP_CHANGE;
-	} else if ((_e->text.len == PRES_WINFO_STR_LEN) && 
-		   !strncasecmp(PRES_WINFO_STR, tmp.s, _e->text.len)) {
-		_e->parsed = EVENT_PRESENCE_WINFO;
-	} else if ((_e->text.len == PRES_SIP_PROFILE_STR_LEN) && 
-		   !strncasecmp(PRES_SIP_PROFILE_STR, tmp.s, _e->text.len)) {
-		_e->parsed = EVENT_SIP_PROFILE;
+		if (parse_params(&tmp, pclass, phooks, &e->params.list) < 0) {
+			ERR("event_parser: Error while parsing parameters parameters\n");
+			return -1;
+		}
 	} else {
-		_e->parsed = EVENT_OTHER;
+		e->params.list = NULL;
 	}
 
 	return 0;
@@ -153,19 +171,24 @@ int parse_event(struct hdr_field* _h)
  */
 void free_event(event_t** _e)
 {
-	if (*_e) pkg_free(*_e);
-	*_e = 0;
+	if (*_e) {
+		if ((*_e)->params.list) free_params((*_e)->params.list);
+		pkg_free(*_e);
+		*_e = NULL;
+	}
 }
 
 
 /*
  * Print structure, for debugging only
  */
-void print_event(event_t* _e)
+void print_event(event_t* e)
 {
 	printf("===Event===\n");
-	printf("text  : \'%.*s\'\n", _e->text.len, ZSW(_e->text.s));
-	printf("parsed: %s\n", 
-	       (_e->parsed == EVENT_PRESENCE) ? ("EVENT_PRESENCE") : ("EVENT_OTHER"));
+	printf("name  : \'%.*s\'\n", STR_FMT(&e->name));
+	printf("type: %d\n", e->type);
+	if (e->params.list) {
+		print_params(stdout, e->params.list);
+	}
 	printf("===/Event===\n");
 }
diff --git a/parser/parse_event.h b/parser/parse_event.h
index 03feb5e..4e90a52 100644
--- a/parser/parse_event.h
+++ b/parser/parse_event.h
@@ -1,12 +1,6 @@
 /*
  * $Id$
  *
- * Event header field body parser
- * This parser was written for Presence Agent module only.
- * it recognizes presence package only, no subpackages, no parameters
- * It should be replaced by a more generic parser if subpackages or
- * parameters should be parsed too.
- *
  * Copyright (C) 2001-2003 FhG Fokus
  *
  * This file is part of ser, a free SIP server.
@@ -37,35 +31,51 @@
 
 #include "../str.h"
 #include "hf.h"
+#include "parse_param.h"
+
+/* Recognized event types */
+enum event_type {
+	EVENT_OTHER = 0,
+	EVENT_PRESENCE,
+	EVENT_PRESENCE_WINFO,
+	EVENT_SIP_PROFILE,
+	EVENT_XCAP_CHANGE,
+	EVENT_DIALOG,
+	EVENT_MESSAGE_SUMMARY
+};
+
+
+struct event_params {
+	struct event_dialog_hooks dialog; /* Well known dialog package params */
+	param_t* list; /* Linked list of all parsed parameters */
+};
 
-#define EVENT_OTHER          0
-#define EVENT_PRESENCE       1
-#define EVENT_PRESENCE_WINFO 2
-#define EVENT_SIP_PROFILE    3
-#define EVENT_XCAP_CHANGE    4
 
 typedef struct event {
-	str text;       /* Original string representation */
-	int parsed;     /* Parsed variant */
+	enum event_type type; /* Parsed variant */
+	str name;             /* Original string representation */
+	struct event_params params;
 } event_t;
 
 
 /*
  * Parse Event HF body
  */
-int parse_event(struct hdr_field* _h);
+int parse_event(struct hdr_field* hf);
 
 
 /*
  * Release memory
  */
-void free_event(event_t** _e);
+void free_event(event_t** e);
 
 
 /*
  * Print structure, for debugging only
  */
-void print_event(event_t* _e);
+void print_event(event_t* e);
+
+int event_parser(char* s, int l, event_t* e);
 
 
 #endif /* PARSE_EVENT_H */




More information about the sr-dev mailing list