1 /*
2  * This file is part of the Sofia-SIP package
3  *
4  * Copyright (C) 2005 Nokia Corporation.
5  *
6  * Contact: Pekka Pessi <pekka.pessi@nokia.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  */
24 
25 /**@CFILE sip_session.c
26  * @brief Session Timer SIP headers.
27  *
28  * The file @b sip_session.c contains implementation of header classes for
29  * session-timer-related SIP headers @SessionExpires and @MinSE.
30  *
31  * @author Pekka Pessi <Pekka.Pessi@nokia.com>.
32  *
33  * @date Created: Thu Sep 13 21:24:15 EEST 2001 ppessi
34  */
35 
36 #include "config.h"
37 
38 /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */
39 #define MSG_PUB_T       struct sip_s
40 #define MSG_HDR_T       union sip_header_u
41 
42 #include "sofia-sip/sip_parser.h"
43 #include <sofia-sip/msg_date.h>
44 
45 #include <stddef.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <stdio.h>
49 #include <assert.h>
50 
51 /* ====================================================================== */
52 
53 /**@SIP_HEADER sip_session_expires Session-Expires Header
54  *
55  * The Session-Expires header is used to convey the lifetime of the session.
56  * Its syntax is defined in @RFC4028 as follows:
57  *
58  * @code
59  *      Session-Expires  =  ("Session-Expires" | "x") HCOLON delta-seconds
60  *                           *(SEMI se-params)
61  *      se-params        = refresher-param / generic-param
62  *      refresher-param  = "refresher" EQUAL  ("uas" / "uac")
63  * @endcode
64  *
65  * The parsed Session-Expires header is stored in #sip_session_expires_t structure.
66  */
67 
68 /**@ingroup sip_session_expires
69  * @typedef typedef struct sip_session_expires_s sip_session_expires_t;
70  *
71  * The structure #sip_session_expires_t contains representation of the SIP
72  * @SessionExpires header.
73  *
74  * The #sip_session_expires_t is defined as follows:
75  * @code
76  * typedef struct sip_session_expires_s
77  * {
78  *  sip_common_t    x_common[1];
79  *  sip_unknown_t  *x_next;
80  *  unsigned long   x_delta; //Delta Seconds
81  *  msg_param_t    *x_params;
82  *  char const     *x_refresher; //Who will send the refresh UAS or UAC
83  * } sip_session_expires_t;
84  * @endcode
85  */
86 
87 static msg_xtra_f sip_session_expires_dup_xtra;
88 static msg_dup_f sip_session_expires_dup_one;
89 static msg_update_f sip_session_expires_update;
90 
91 msg_hclass_t sip_session_expires_class[] =
92 SIP_HEADER_CLASS(session_expires, "Session-Expires", "x", x_params, single,
93 		 session_expires);
94 
sip_session_expires_d(su_home_t * home,sip_header_t * h,char * s,isize_t slen)95 issize_t sip_session_expires_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
96 {
97   sip_session_expires_t *x = h->sh_session_expires;
98 
99   if (msg_delta_d((char const **) &s, &x->x_delta) < 0)
100     return -1;
101   if (*s == ';') {
102     if (msg_params_d(home, &s, &x->x_params) < 0 || *s)
103       return -1;
104      x->x_refresher = msg_params_find(x->x_params, "refresher");
105   }
106   return 0;
107 }
108 
sip_session_expires_e(char b[],isize_t bsiz,sip_header_t const * h,int flags)109 issize_t sip_session_expires_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
110 {
111   char *end = b + bsiz, *b0 = b;
112   int n = 0;
113   sip_session_expires_t const *o = h->sh_session_expires;
114 
115   n = snprintf(b, bsiz, "%lu", o->x_delta);
116   b += n;
117   MSG_PARAMS_E(b, end, o->x_params, flags);
118 
119   return b - b0;
120 }
121 
sip_session_expires_dup_xtra(sip_header_t const * h,isize_t offset)122 isize_t sip_session_expires_dup_xtra(sip_header_t const *h, isize_t offset)
123 {
124   sip_session_expires_t const *o = h->sh_session_expires;
125 
126   MSG_PARAMS_SIZE(offset, o->x_params);
127 
128   return offset;
129 }
130 
131 /** Duplicate one #sip_session_expires_t object */
sip_session_expires_dup_one(sip_header_t * dst,sip_header_t const * src,char * b,isize_t xtra)132 char *sip_session_expires_dup_one(sip_header_t *dst, sip_header_t const *src,
133 				  char *b, isize_t xtra)
134 {
135   sip_session_expires_t *o_dst = dst->sh_session_expires;
136   sip_session_expires_t const *o_src = src->sh_session_expires;
137 
138   char *end = b + xtra;
139   b = msg_params_dup(&o_dst->x_params, o_src->x_params, b, xtra);
140   o_dst->x_delta = o_src->x_delta;
141   assert(b <= end); (void)end;
142 
143   return b;
144 }
145 
146 /** Update parameters in @SessionExpires header. */
sip_session_expires_update(msg_common_t * h,char const * name,isize_t namelen,char const * value)147 static int sip_session_expires_update(msg_common_t *h,
148 				      char const *name, isize_t namelen,
149 				      char const *value)
150 {
151   sip_session_expires_t *x = (sip_session_expires_t *)h;
152 
153   if (name == NULL) {
154     x->x_refresher = NULL;
155   }
156   else if (namelen == strlen("refresher") &&
157 	   su_casenmatch(name, "refresher", namelen)) {
158     x->x_refresher = value;
159   }
160 
161   return 0;
162 }
163 
164 
165 
166 /**@SIP_HEADER sip_min_se Min-SE Header
167  *
168  * The Min-SE header is used to indicate the minimum value for the session
169  * interval. Its syntax is defined in @RFC4028 as follows:
170  *
171  * @code
172  *      MMin-SE  =  "Min-SE" HCOLON delta-seconds *(SEMI generic-param)
173  * @endcode
174  *
175  * The parsed Min-SE header is stored in #sip_min_se_t structure.
176  */
177 
178 /**@ingroup sip_min_se
179  * @typedef typedef struct sip_min_se_s sip_min_se_t;
180  *
181  * The structure #sip_min_se_t contains representation of the SIP
182  * @MinSE header.
183  *
184  * The #sip_min_se_t is defined as follows:
185  * @code
186  * typedef struct sip_min_se_s
187  * {
188  *   sip_common_t    min_common[1];
189  *   sip_unknown_t  *min_next;
190  *   unsigned long   min_delta;   // Delta seconds
191  *   sip_params_t   *min_params;  // List of extension parameters
192  * } sip_min_se_t;
193  * @endcode
194  */
195 
196 static msg_xtra_f sip_min_se_dup_xtra;
197 static msg_dup_f sip_min_se_dup_one;
198 #define sip_min_se_update NULL
199 
200 msg_hclass_t sip_min_se_class[] =
201 SIP_HEADER_CLASS(min_se, "Min-SE", "", min_params, single, min_se);
202 
sip_min_se_d(su_home_t * home,sip_header_t * h,char * s,isize_t slen)203 issize_t sip_min_se_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
204 {
205   sip_min_se_t *min = h->sh_min_se;
206 
207   if (msg_delta_d((char const **) &s, &min->min_delta) < 0)
208     return -1;
209   if (*s == ';') {
210     if (msg_params_d(home, &s, &min->min_params) < 0 || *s)
211       return -1;
212   }
213 
214   return 0;
215 }
216 
sip_min_se_e(char b[],isize_t bsiz,sip_header_t const * h,int flags)217 issize_t sip_min_se_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
218 {
219   char *end = b + bsiz, *b0 = b;
220   int n = 0;
221   sip_min_se_t const *o = (sip_min_se_t *)h;
222 
223   n = snprintf(b, bsiz, "%lu", o->min_delta);
224   b += n;
225   MSG_PARAMS_E(b, end, o->min_params, flags);
226 
227   return b - b0;
228 }
229 
sip_min_se_dup_xtra(sip_header_t const * h,isize_t offset)230 isize_t sip_min_se_dup_xtra(sip_header_t const *h, isize_t offset)
231 {
232   sip_min_se_t const *o = (sip_min_se_t *)h;
233 
234   MSG_PARAMS_SIZE(offset, o->min_params);
235 
236   return offset;
237 }
238 
239 /** Duplicate one #sip_min_se_t object */
sip_min_se_dup_one(sip_header_t * dst,sip_header_t const * src,char * b,isize_t xtra)240 char *sip_min_se_dup_one(sip_header_t *dst, sip_header_t const *src,
241 			char *b, isize_t xtra)
242 {
243   sip_min_se_t *o_dst = (sip_min_se_t *)dst;
244   sip_min_se_t const *o_src = (sip_min_se_t *)src;
245 
246   char *end = b + xtra;
247   b = msg_params_dup(&o_dst->min_params, o_src->min_params, b, xtra);
248   o_dst->min_delta = o_src->min_delta;
249   assert(b <= end); (void)end;
250 
251   return b;
252 }
253