sip_reason.c 4.91 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
 * 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_reason.c
26
 * @brief @Reason header.
Pekka Pessi's avatar
Pekka Pessi committed
27
 *
28
 * The file @b sip_reason.c contains implementation of header class for
29
 * SIP header @Reason.
Pekka Pessi's avatar
Pekka Pessi committed
30 31 32 33 34 35
 *
 * @author Pekka Pessi <Pekka.Pessi@nokia.com>.
 */

#include "config.h"

36 37 38 39 40 41
/* 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"

Pekka Pessi's avatar
Pekka Pessi committed
42 43 44
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
Pekka Pessi's avatar
Pekka Pessi committed
45 46
#include <limits.h>

Pekka Pessi's avatar
Pekka Pessi committed
47 48 49 50 51 52
#include <assert.h>

/**@SIP_HEADER sip_reason Reason Header
 *
 * The Reason header is used to indicate why a SIP request was issued or why
 * a provisional response was sent. It can be used with HRPF scenarios. It
53
 * is defined in @RFC3326 as follows:
Pekka Pessi's avatar
Pekka Pessi committed
54 55 56 57 58 59 60 61 62 63 64 65 66
 * 
 * @code
 *   Reason            =  "Reason" HCOLON reason-value *(COMMA reason-value)
 *   reason-value      =  protocol *(SEMI reason-params)
 *   protocol          =  "SIP" / "Q.850" / token
 *   reason-params     =  protocol-cause / reason-text
 *                        / reason-extension
 *   protocol-cause    =  "cause" EQUAL cause
 *   cause             =  1*DIGIT
 *   reason-text       =  "text" EQUAL quoted-string
 *   reason-extension  =  generic-param
 * @endcode
 * 
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
 * The parsed Reason header is stored in #sip_reason_t structure.
 */

/**@ingroup sip_reason
 * @typedef typedef struct sip_reason_s sip_reason_t;
 *
 * The structure #sip_reason_t contains representation of SIP @Reason header.
 *
 * The #sip_reason_t is defined as follows:
 * @code
 * typedef struct sip_reason_s
 * {
 *   sip_common_t        re_common[1]; // Common fragment info 
 *   sip_reason_t       *re_next;      // Link to next <reason-value> 
 *   char const         *re_protocol;  // Protocol 
 *   msg_param_t const  *re_params;    // List of reason parameters 
 *   char const         *re_cause;     // Value of cause parameter 
 *   char const         *re_text;      // Value of text parameter 
 * } sip_reason_t;
 * @endcode
Pekka Pessi's avatar
Pekka Pessi committed
87 88 89 90
 */

static msg_xtra_f sip_reason_dup_xtra;
static msg_dup_f sip_reason_dup_one;
91
static msg_update_f sip_reason_update;
Pekka Pessi's avatar
Pekka Pessi committed
92 93 94 95

msg_hclass_t sip_reason_class[] = 
SIP_HEADER_CLASS(reason, "Reason", "", re_params, append, reason);

96
issize_t sip_reason_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
Pekka Pessi's avatar
Pekka Pessi committed
97
{
98
  sip_reason_t *re = (sip_reason_t *)h;
99
  size_t n;
Pekka Pessi's avatar
Pekka Pessi committed
100

101 102 103 104 105 106 107 108 109 110 111
  while (*s == ',')   /* Ignore empty entries (comma-whitespace) */
    *s = '\0', s += span_lws(s + 1) + 1;

  re->re_protocol = s;
  if ((n = span_token(s)) == 0) 
    return -1;
  s += n; while (IS_LWS(*s)) *s++ = '\0'; 
  if (*s == ';' && msg_params_d(home, &s, &re->re_params) < 0)
    return -1;

  return msg_parse_next_field(home, h, s, slen);
Pekka Pessi's avatar
Pekka Pessi committed
112 113
}

114
issize_t sip_reason_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
Pekka Pessi's avatar
Pekka Pessi committed
115 116 117 118 119
{
  char *end = b + bsiz, *b0 = b;
  sip_reason_t const *re = h->sh_reason;

  assert(sip_is_reason(h));
Pekka Pessi's avatar
Pekka Pessi committed
120 121
  MSG_STRING_E(b, end, re->re_protocol);
  MSG_PARAMS_E(b, end, re->re_params, flags);
Pekka Pessi's avatar
Pekka Pessi committed
122 123 124 125

  return b - b0;
}

126
isize_t sip_reason_dup_xtra(sip_header_t const *h, isize_t offset)
Pekka Pessi's avatar
Pekka Pessi committed
127 128 129
{
  sip_reason_t const *re = h->sh_reason;

Pekka Pessi's avatar
Pekka Pessi committed
130 131
  MSG_PARAMS_SIZE(offset, re->re_params);
  offset += MSG_STRING_SIZE(re->re_protocol);
Pekka Pessi's avatar
Pekka Pessi committed
132 133 134 135

  return offset;
}

136
/** Duplicate one #sip_reason_t object */ 
Pekka Pessi's avatar
Pekka Pessi committed
137
char *sip_reason_dup_one(sip_header_t *dst, sip_header_t const *src,
138
			char *b, isize_t xtra)
Pekka Pessi's avatar
Pekka Pessi committed
139 140 141 142 143
{
  sip_reason_t *re_dst = dst->sh_reason;
  sip_reason_t const *re_src = src->sh_reason;

  char *end = b + xtra;
Pekka Pessi's avatar
Pekka Pessi committed
144 145
  b = msg_params_dup(&re_dst->re_params, re_src->re_params, b, xtra);
  MSG_STRING_DUP(b, re_dst->re_protocol, re_src->re_protocol);
146
  assert(b <= end); (void)end;
Pekka Pessi's avatar
Pekka Pessi committed
147 148 149 150

  return b;
}

151
/** Update parameter values for @Reason header */
152
static int sip_reason_update(msg_common_t *h, 
153
			     char const *name, isize_t namelen,
154
			     char const *value)
Pekka Pessi's avatar
Pekka Pessi committed
155
{
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
  sip_reason_t *re = (sip_reason_t *)h;

  if (name == NULL) {
    re->re_cause = NULL;
    re->re_text = NULL;
  }
#define MATCH(s) (namelen == strlen(#s) && !strncasecmp(name, #s, strlen(#s)))

  else if (MATCH(cause)) {
    re->re_cause = value;
  }
  else if (MATCH(text)) {
    re->re_text = value;
  }

#undef MATCH

  return 0;
Pekka Pessi's avatar
Pekka Pessi committed
174
}