sip_session.c 6.89 KB
Newer Older
Pekka Pessi's avatar
Pekka Pessi committed
1 2 3 4 5 6 7
/*
 * This file is part of the Sofia-SIP package
 *
 * Copyright (C) 2005 Nokia Corporation.
 *
 * Contact: Pekka Pessi <pekka.pessi@nokia.com>
 *
8
 * This library is free software; you can redistribute it and/or
Pekka Pessi's avatar
Pekka Pessi committed
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

/**@CFILE sip_session.c
 * @brief Session Timer SIP headers.
 *
 * The file @b sip_session.c contains implementation of header classes for
29
 * session-timer-related SIP headers @SessionExpires and @MinSE.
Pekka Pessi's avatar
Pekka Pessi committed
30 31 32 33 34 35 36 37
 *
 * @author Pekka Pessi <Pekka.Pessi@nokia.com>.
 *
 * @date Created: Thu Sep 13 21:24:15 EEST 2001 ppessi
 */

#include "config.h"

38 39 40 41 42 43 44
/* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */
#define MSG_PUB_T       struct sip_s
#define MSG_HDR_T       union sip_header_u

#include "sofia-sip/sip_parser.h"
#include <sofia-sip/msg_date.h>

Pekka Pessi's avatar
Pekka Pessi committed
45 46 47 48
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
49
#include <assert.h>
Pekka Pessi's avatar
Pekka Pessi committed
50 51 52 53 54

/* ====================================================================== */

/**@SIP_HEADER sip_session_expires Session-Expires Header
 *
55
 * The Session-Expires header is used to convey the lifetime of the session.
56
 * Its syntax is defined in @RFC4028 as follows:
57
 *
Pekka Pessi's avatar
Pekka Pessi committed
58
 * @code
59 60 61 62
 *      Session-Expires  =  ("Session-Expires" | "x") HCOLON delta-seconds
 *                           *(SEMI se-params)
 *      se-params        = refresher-param / generic-param
 *      refresher-param  = "refresher" EQUAL  ("uas" / "uac")
Pekka Pessi's avatar
Pekka Pessi committed
63
 * @endcode
64 65 66 67 68 69 70 71 72 73 74
 *
 * The parsed Session-Expires header is stored in #sip_session_expires_t structure.
 */

/**@ingroup sip_session_expires
 * @typedef typedef struct sip_session_expires_s sip_session_expires_t;
 *
 * The structure #sip_session_expires_t contains representation of the SIP
 * @SessionExpires header.
 *
 * The #sip_session_expires_t is defined as follows:
Pekka Pessi's avatar
Pekka Pessi committed
75 76 77 78 79 80
 * @code
 * typedef struct sip_session_expires_s
 * {
 *  sip_common_t    x_common[1];
 *  sip_unknown_t  *x_next;
 *  unsigned long   x_delta; //Delta Seconds
81
 *  msg_param_t    *x_params;
Pekka Pessi's avatar
Pekka Pessi committed
82 83 84 85 86 87 88
 *  char const     *x_refresher; //Who will send the refresh UAS or UAC
 * } sip_session_expires_t;
 * @endcode
 */

static msg_xtra_f sip_session_expires_dup_xtra;
static msg_dup_f sip_session_expires_dup_one;
89
static msg_update_f sip_session_expires_update;
Pekka Pessi's avatar
Pekka Pessi committed
90 91

msg_hclass_t sip_session_expires_class[] =
92
SIP_HEADER_CLASS(session_expires, "Session-Expires", "x", x_params, single,
Pekka Pessi's avatar
Pekka Pessi committed
93 94
		 session_expires);

95
issize_t sip_session_expires_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
Pekka Pessi's avatar
Pekka Pessi committed
96 97 98 99 100 101 102 103
{
  sip_session_expires_t *x = h->sh_session_expires;

  if (msg_delta_d((char const **) &s, &x->x_delta) < 0)
    return -1;
  if (*s == ';') {
    if (msg_params_d(home, &s, &x->x_params) < 0 || *s)
      return -1;
Pekka Pessi's avatar
Pekka Pessi committed
104
     x->x_refresher = msg_params_find(x->x_params, "refresher");
Pekka Pessi's avatar
Pekka Pessi committed
105 106 107 108
  }
  return 0;
}

109
issize_t sip_session_expires_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
Pekka Pessi's avatar
Pekka Pessi committed
110 111 112 113 114 115
{
  char *end = b + bsiz, *b0 = b;
  int n = 0;
  sip_session_expires_t const *o = h->sh_session_expires;

  n = snprintf(b, bsiz, "%lu", o->x_delta);
116
  b += n;
Pekka Pessi's avatar
Pekka Pessi committed
117
  MSG_PARAMS_E(b, end, o->x_params, flags);
Pekka Pessi's avatar
Pekka Pessi committed
118 119 120 121

  return b - b0;
}

122
isize_t sip_session_expires_dup_xtra(sip_header_t const *h, isize_t offset)
Pekka Pessi's avatar
Pekka Pessi committed
123 124 125
{
  sip_session_expires_t const *o = h->sh_session_expires;

Pekka Pessi's avatar
Pekka Pessi committed
126
  MSG_PARAMS_SIZE(offset, o->x_params);
127

Pekka Pessi's avatar
Pekka Pessi committed
128 129 130
  return offset;
}

131
/** Duplicate one #sip_session_expires_t object */
Pekka Pessi's avatar
Pekka Pessi committed
132
char *sip_session_expires_dup_one(sip_header_t *dst, sip_header_t const *src,
133
				  char *b, isize_t xtra)
Pekka Pessi's avatar
Pekka Pessi committed
134 135 136 137 138
{
  sip_session_expires_t *o_dst = dst->sh_session_expires;
  sip_session_expires_t const *o_src = src->sh_session_expires;

  char *end = b + xtra;
Pekka Pessi's avatar
Pekka Pessi committed
139
  b = msg_params_dup(&o_dst->x_params, o_src->x_params, b, xtra);
Pekka Pessi's avatar
Pekka Pessi committed
140
  o_dst->x_delta = o_src->x_delta;
141
  assert(b <= end); (void)end;
Pekka Pessi's avatar
Pekka Pessi committed
142 143 144 145

  return b;
}

146
/** Update parameters in @SessionExpires header. */
147
static int sip_session_expires_update(msg_common_t *h,
148
				      char const *name, isize_t namelen,
149 150 151 152 153 154 155
				      char const *value)
{
  sip_session_expires_t *x = (sip_session_expires_t *)h;

  if (name == NULL) {
    x->x_refresher = NULL;
  }
156
  else if (namelen == strlen("refresher") &&
157 158 159 160 161 162 163 164
	   !strncasecmp(name, "refresher", namelen)) {
    x->x_refresher = value;
  }

  return 0;
}


Pekka Pessi's avatar
Pekka Pessi committed
165 166 167 168

/**@SIP_HEADER sip_min_se Min-SE Header
 *
 * 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
 *
Pekka Pessi's avatar
Pekka Pessi committed
171
 * @code
172
 *      MMin-SE  =  "Min-SE" HCOLON delta-seconds *(SEMI generic-param)
Pekka Pessi's avatar
Pekka Pessi committed
173
 * @endcode
174 175 176 177 178 179 180 181 182 183 184
 *
 * The parsed Min-SE header is stored in #sip_min_se_t structure.
 */

/**@ingroup sip_min_se
 * @typedef typedef struct sip_min_se_s sip_min_se_t;
 *
 * The structure #sip_min_se_t contains representation of the SIP
 * @MinSE header.
 *
 * The #sip_min_se_t is defined as follows:
Pekka Pessi's avatar
Pekka Pessi committed
185 186 187
 * @code
 * typedef struct sip_min_se_s
 * {
188 189 190 191
 *   sip_common_t    min_common[1];
 *   sip_unknown_t  *min_next;
 *   unsigned long   min_delta;   // Delta seconds
 *   sip_params_t   *min_params;  // List of extension parameters
Pekka Pessi's avatar
Pekka Pessi committed
192 193 194 195 196 197
 * } sip_min_se_t;
 * @endcode
 */

static msg_xtra_f sip_min_se_dup_xtra;
static msg_dup_f sip_min_se_dup_one;
198
#define sip_min_se_update NULL
Pekka Pessi's avatar
Pekka Pessi committed
199 200

msg_hclass_t sip_min_se_class[] =
201
SIP_HEADER_CLASS(min_se, "Min-SE", "", min_params, single, min_se);
Pekka Pessi's avatar
Pekka Pessi committed
202

203
issize_t sip_min_se_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
Pekka Pessi's avatar
Pekka Pessi committed
204 205 206 207 208
{
  sip_min_se_t *min = h->sh_min_se;

  if (msg_delta_d((char const **) &s, &min->min_delta) < 0)
    return -1;
209 210 211 212
  if (*s == ';') {
    if (msg_params_d(home, &s, &min->min_params) < 0 || *s)
      return -1;
  }
Pekka Pessi's avatar
Pekka Pessi committed
213 214 215 216

  return 0;
}

217
issize_t sip_min_se_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
Pekka Pessi's avatar
Pekka Pessi committed
218
{
219 220 221
  char *end = b + bsiz, *b0 = b;
  int n = 0;
  sip_min_se_t const *o = (sip_min_se_t *)h;
Pekka Pessi's avatar
Pekka Pessi committed
222

223
  n = snprintf(b, bsiz, "%lu", o->min_delta);
224
  b += n;
225
  MSG_PARAMS_E(b, end, o->min_params, flags);
Pekka Pessi's avatar
Pekka Pessi committed
226

227
  return b - b0;
Pekka Pessi's avatar
Pekka Pessi committed
228 229
}

230
isize_t sip_min_se_dup_xtra(sip_header_t const *h, isize_t offset)
Pekka Pessi's avatar
Pekka Pessi committed
231
{
232 233 234
  sip_min_se_t const *o = (sip_min_se_t *)h;

  MSG_PARAMS_SIZE(offset, o->min_params);
235

Pekka Pessi's avatar
Pekka Pessi committed
236 237 238
  return offset;
}

239
/** Duplicate one #sip_min_se_t object */
Pekka Pessi's avatar
Pekka Pessi committed
240
char *sip_min_se_dup_one(sip_header_t *dst, sip_header_t const *src,
241
			char *b, isize_t xtra)
Pekka Pessi's avatar
Pekka Pessi committed
242
{
243 244
  sip_min_se_t *o_dst = (sip_min_se_t *)dst;
  sip_min_se_t const *o_src = (sip_min_se_t *)src;
Pekka Pessi's avatar
Pekka Pessi committed
245 246

  char *end = b + xtra;
247
  b = msg_params_dup(&o_dst->min_params, o_src->min_params, b, xtra);
Pekka Pessi's avatar
Pekka Pessi committed
248
  o_dst->min_delta = o_src->min_delta;
249
  assert(b <= end); (void)end;
Pekka Pessi's avatar
Pekka Pessi committed
250 251 252

  return b;
}