f7260bc8f65bb1134285b49a351f32e856e60e5b
[sip-router] / parser / parse_subscription_state.c
1 /*! \file
2  * \brief Parser :: Parse subscription-state in NOTIFY
3  *
4  * \ingroup parser
5  */
6
7 #include "parse_subscription_state.h"
8 #include "../dprint.h"
9 #include "../trim.h"
10 #include "../mem/mem.h"
11 #include "../ut.h"
12 #include "parser_f.h"
13 #include "parse_param.h"
14 #include <string.h>
15
16 void free_subscription_state(subscription_state_t**ss)
17 {
18         if (ss) {
19                 if (*ss) pkg_free(*ss);
20                 *ss = 0;
21         }
22 }
23
24 static inline int str_cmp(const str *a, const str *b)
25 {
26         int i;
27         
28         if (a->len != b->len) return 1;
29         
30         for (i = 0; i < a->len; i++) 
31                 if (a->s[i] != b->s[i]) return 1;
32         return 0;
33 }
34
35 static int ss_parse(str *src, subscription_state_t *ss)
36 {
37         static str active = STR_STATIC_INIT("active");
38         static str pending = STR_STATIC_INIT("pending");
39         static str terminated = STR_STATIC_INIT("terminated");
40         
41         int res = 0;
42         param_hooks_t ph;
43         param_t *params;
44         str s = *src;
45         str state;
46         char *c, *end;
47         
48         /* initialization */
49         ss->expires_set = 0;
50         ss->expires = 0;
51         
52         trim_leading(&s);
53         end = s.s + s.len;
54                 
55         state = s;
56         
57         c = find_not_quoted(&s, ';');
58         if (c) {
59                 /* first parameter starts after c */
60                 state.len = c - state.s;
61                 s.len = s.len - (c - s.s) - 1;
62                 s.s = c + 1;
63         }
64         else {
65                 s.len = 0;
66         }
67
68         /* set state value */
69         trim(&state);
70         if (str_cmp(&state, &active) == 0) {
71                 ss->value = ss_active;
72         }
73         else if (str_cmp(&state, &pending) == 0) {
74                 ss->value = ss_pending;
75         }
76         else if (str_cmp(&state, &terminated) == 0) {
77                 ss->value = ss_terminated;
78         }
79         else { 
80                 /* INFO("unknown subscription-State value :%.*s\n",
81                                         state.len, state.s); */
82                 ss->value = ss_extension;
83         }
84
85         /* explore parameters */
86         
87         trim_leading(&s);
88         if (s.len > 0) {
89                 params = NULL;
90                 if (parse_params(&s, CLASS_CONTACT, &ph, &params) < 0) {
91                         ERR("can't parse params\n");
92                         res = -1;
93                 }
94                 else {
95                         if (ph.contact.expires) {
96                                 ss->expires_set = 1;
97                                 res = str2int(&ph.contact.expires->body, &ss->expires);
98                                 if (res != 0) 
99                                         ERR("invalid expires value: \'%.*s\'\n", 
100                                                 ph.contact.expires->body.len,
101                                                 ph.contact.expires->body.s);
102                         }
103                         if (params) free_params(params);
104                 }
105         }
106         /*
107         ss->value = ss_active;
108         ss->expires = 0;*/
109
110
111         return res;
112 }
113
114 int parse_subscription_state(struct hdr_field *h)
115 {
116         subscription_state_t *ss;
117         if (h->parsed) return 0;
118
119         ss = (subscription_state_t*)pkg_malloc(sizeof(*ss));
120         if (!ss) {
121                 ERR("No memory left\n");
122                 return -1;
123         }
124
125         memset(ss, 0, sizeof(*ss));
126
127         if (ss_parse(&h->body, ss) < 0) {
128                 ERR("Can't parse Subscription-State\n");
129                 pkg_free(ss);
130                 return -2;
131         }
132
133         h->parsed = (void*)ss;
134         
135         return 0;
136 }