core, lib, modules: restructured source code tree
[sip-router] / src / core / parser / parse_event.c
1 /*
2  * Event header field body parser.
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 /*! \file
25  * \brief Parser :: Event header field body parser.
26  *
27  * The parser was written for Presence Agent module only.
28  * it recognize presence package only, no sub-packages, no parameters
29  * It should be replaced by a more generic parser if sub-packages or
30  * parameters should be parsed too.
31  *
32  * \ingroup parser
33  */
34
35
36 #include "parse_event.h"
37 #include "../mem/mem.h"    /* pkg_malloc, pkg_free */
38 #include "../dprint.h"
39 #include <string.h>        /* memset */
40 #include "../trim.h"       /* trim_leading */
41 #include <stdio.h>         /* printf */
42 #include "../ut.h"
43
44 static struct {
45         str name;
46         int type;       
47 } events[] = {
48         {STR_STATIC_INIT("presence"),        EVENT_PRESENCE},
49         {STR_STATIC_INIT("presence.winfo"),  EVENT_PRESENCE_WINFO},
50         {STR_STATIC_INIT("xcap-change"),     EVENT_XCAP_CHANGE},
51         {STR_STATIC_INIT("sip-profile"),     EVENT_SIP_PROFILE},
52         {STR_STATIC_INIT("message-summary"), EVENT_MESSAGE_SUMMARY},
53         {STR_STATIC_INIT("dialog"),          EVENT_DIALOG},
54         {STR_STATIC_INIT("ua-profile"),      EVENT_UA_PROFILE},
55         /* The following must be the last element in the array */
56         {STR_NULL,                           EVENT_OTHER}
57 };
58
59
60 static inline char* skip_token(char* _b, int _l)
61 {
62         int i = 0;
63
64         for(i = 0; i < _l; i++) {
65                 switch(_b[i]) {
66                 case ' ':
67                 case '\r':
68                 case '\n':
69                 case '\t':
70                 case ';':
71                         return _b + i;
72                 }
73         }
74
75         return _b + _l;
76 }
77
78
79 int event_parser(char* s, int len, event_t* e)
80 {
81         int i;
82         str tmp;
83         char* end;
84         param_hooks_t* phooks = NULL;
85         enum pclass pclass = CLASS_ANY;
86
87         if (e == NULL) {
88                 ERR("event_parser: Invalid parameter value\n");
89                 return -1;
90         }
91
92         tmp.s = s;
93         tmp.len = len;
94         trim_leading(&tmp);
95
96         if (tmp.len == 0) {
97                 LOG(L_ERR, "event_parser: Empty body\n");
98                 return -1;
99         }
100
101         e->name.s = tmp.s;
102         end = skip_token(tmp.s, tmp.len);
103         e->name.len = end - tmp.s;
104
105         e->type = EVENT_OTHER;
106         for(i = 0; events[i].name.len; i++) {
107                 if (e->name.len == events[i].name.len &&
108                         !strncasecmp(e->name.s, events[i].name.s, e->name.len)) {
109                         e->type = events[i].type;
110                         break;
111                 }
112         }
113
114         tmp.len -= end - tmp.s;
115         tmp.s = end;
116         trim_leading(&tmp);
117
118         e->params.list = NULL;
119         
120         if (tmp.len && (tmp.s[0] == ';')) {
121                 /* Shift the semicolon and skip any leading whitespace, this is needed
122                  * for parse_params to work correctly. */
123                 tmp.s++; tmp.len--;
124                 trim_leading(&tmp);
125                 if (!tmp.len) return 0;
126
127                 /* We have parameters to parse */
128                 if (e->type == EVENT_DIALOG) {
129                         pclass = CLASS_EVENT_DIALOG;
130                         phooks = (param_hooks_t*)&e->params.hooks;
131                 }
132
133                 if (parse_params(&tmp, pclass, phooks, &e->params.list) < 0) {
134                         ERR("event_parser: Error while parsing parameters parameters\n");
135                         return -1;
136                 }
137         }
138         return 0;
139 }
140
141
142 /*! \brief
143  * Parse Event header field body
144  */
145 int parse_event(struct hdr_field* _h)
146 {
147         event_t* e;
148
149         if (_h->parsed != 0) {
150                 return 0;
151         }
152
153         e = (event_t*)pkg_malloc(sizeof(event_t));
154         if (e == 0) {
155                 LOG(L_ERR, "parse_event(): No memory left\n");
156                 return -1;
157         }
158
159         memset(e, 0, sizeof(event_t));
160
161         if (event_parser(_h->body.s, _h->body.len, e) < 0) {
162                 LOG(L_ERR, "parse_event(): Error in event_parser\n");
163                 pkg_free(e);
164                 return -2;
165         }
166
167         _h->parsed = (void*)e;
168         return 0;
169 }
170
171
172 /*! \brief
173  * Free all memory
174  */
175 void free_event(event_t** _e)
176 {
177         if (*_e) {
178                 if ((*_e)->params.list) free_params((*_e)->params.list);
179                 pkg_free(*_e);
180                 *_e = NULL;
181         }
182 }
183
184
185 /*! \brief
186  * Print structure, for debugging only
187  */
188 void print_event(event_t* e)
189 {
190         fprintf(stderr, "===Event===\n");
191         fprintf(stderr, "name  : \'%.*s\'\n", STR_FMT(&e->name));
192         fprintf(stderr, "type: %d\n", e->type);
193         if (e->params.list) {
194                 print_params(stderr, e->params.list);
195         }
196         fprintf(stderr, "===/Event===\n");
197 }