sip_prack.c 5.58 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_prack.c
 * @brief SIP headers for Prack.
 *
 * The file @b sip_prack.c contains implementation of header classes for
29
 * PRACK-related SIP headers @RAck and @RSeq.
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
/* 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
44 45 46 47
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
48
#include <assert.h>
Pekka Pessi's avatar
Pekka Pessi committed
49
#include <limits.h>
Pekka Pessi's avatar
Pekka Pessi committed
50 51 52 53 54 55 56

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

/**@SIP_HEADER sip_rack RAck Header
 *
 * The RAck header indicates the sequence number of the provisional response
 * which is being acknowledged.  Its syntax is defined in
57
 * @RFC3262 section 10 as follows:
58
 *
Pekka Pessi's avatar
Pekka Pessi committed
59
 * @code
60
 *    RAck          =  "RAck" HCOLON response-num LWS CSeq-num LWS Method
Pekka Pessi's avatar
Pekka Pessi committed
61 62 63 64
 *    response-num  =  1*DIGIT
 *    CSeq-num      =  1*DIGIT
 * @endcode
 *
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
 * @sa @RFC3262, nta_outgoing_prack(), nta_reliable_treply(),
 *   nta_reliable_mreply().
 *
 * The parsed RAck header is stored in #sip_rack_t structure.
 */

/**@ingroup sip_rack
 * @typedef struct sip_rack_s sip_rack_t;
 *
 * The structure #sip_rack_t contains representation of an @RAck header.
 *
 * The #sip_rack_t is defined as follows:
 * @code
 * typedef struct sip_rack_s
 * {
 *   sip_common_t        ra_common;        // Common fragment info
 *   sip_error_t        *ra_next;          // Dummy link to next
 *   uint32_t            ra_response;      // Sequence number of response
 *   uint32_t            ra_cseq;          // Sequence number of request
 *   sip_method_t        ra_method;        // Original request method
 *   char const         *ra_method_name;   // Original request method name
 * } sip_rack_t;
 * @endcode
Pekka Pessi's avatar
Pekka Pessi committed
88 89 90 91
 */

static msg_xtra_f sip_rack_dup_xtra;
static msg_dup_f sip_rack_dup_one;
92
#define sip_rack_update NULL
Pekka Pessi's avatar
Pekka Pessi committed
93

94
msg_hclass_t sip_rack_class[] =
Pekka Pessi's avatar
Pekka Pessi committed
95 96
SIP_HEADER_CLASS(rack, "RAck", "", ra_common, single, rack);

97
issize_t sip_rack_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
Pekka Pessi's avatar
Pekka Pessi committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
{
  sip_rack_t *ra = h->sh_rack;

  ra->ra_response = strtoul(s, &s, 10);

  if (IS_LWS(*s)) {
    skip_lws(&s);
    ra->ra_cseq = strtoul(s, &s, 10);

    if (IS_LWS(*s)) {
      skip_lws(&s);
      if ((ra->ra_method = sip_method_d(&s, &ra->ra_method_name)) >= 0) {
	return 0;
      }
    }
  }

  return -1;
}

118
issize_t sip_rack_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
Pekka Pessi's avatar
Pekka Pessi committed
119 120 121 122 123
{
  sip_rack_t const *ra = h->sh_rack;

  assert(sip_is_rack(h));

124
  return snprintf(b, bsiz, "%u %u %s",
Pekka Pessi's avatar
Pekka Pessi committed
125 126 127
		  ra->ra_response, ra->ra_cseq, ra->ra_method_name);
}

128
isize_t sip_rack_dup_xtra(sip_header_t const *h, isize_t offset)
Pekka Pessi's avatar
Pekka Pessi committed
129 130 131 132
{
  sip_rack_t const *ra = h->sh_rack;

  if (ra->ra_method == sip_method_unknown)
Pekka Pessi's avatar
Pekka Pessi committed
133
    return offset + MSG_STRING_SIZE(ra->ra_method_name);
Pekka Pessi's avatar
Pekka Pessi committed
134 135 136 137
  else
    return offset;
}

138
/** Duplicate one #sip_rack_t object */
Pekka Pessi's avatar
Pekka Pessi committed
139
char *sip_rack_dup_one(sip_header_t *dst, sip_header_t const *src,
140
			char *b, isize_t xtra)
Pekka Pessi's avatar
Pekka Pessi committed
141 142 143 144 145 146 147 148 149 150 151
{
  sip_rack_t *ra_dst = dst->sh_rack;
  sip_rack_t const *ra_src = src->sh_rack;

  char *end = b + xtra;

  ra_dst->ra_response = ra_src->ra_response;
  ra_dst->ra_cseq     = ra_src->ra_cseq;
  ra_dst->ra_method   = ra_src->ra_method;

  if (ra_src->ra_method == sip_method_unknown)
Pekka Pessi's avatar
Pekka Pessi committed
152
    MSG_STRING_DUP(b, ra_dst->ra_method_name, ra_src->ra_method_name);
Pekka Pessi's avatar
Pekka Pessi committed
153 154 155
  else
    ra_dst->ra_method_name = ra_src->ra_method_name;

156
  assert(b <= end); (void)end;
Pekka Pessi's avatar
Pekka Pessi committed
157 158 159 160 161 162 163 164

  return b;
}

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

/**@SIP_HEADER sip_rseq RSeq Header
 *
165
 * The RSeq header identifies provisional responses within a transaction.
166
 * Its syntax is defined in @RFC3262 section 10 as follows:
167
 *
Pekka Pessi's avatar
Pekka Pessi committed
168
 * @code
169
 *    RSeq          =  "RSeq" HCOLON response-num
Pekka Pessi's avatar
Pekka Pessi committed
170 171 172
 *    response-num  =  1*DIGIT
 * @endcode
 *
173
 * The parsed RSeq header is stored in #sip_rseq_t structure.
Pekka Pessi's avatar
Pekka Pessi committed
174 175
 */

176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
/**@ingroup sip_rseq
 * @typedef struct sip_rseq_s sip_rseq_t;
 *
 * The structure #sip_rseq_t contains representation of an @RSeq header.
 *
 * The #sip_rseq_t is defined as follows:
 * @code
 * typedef struct sip_rseq_s
 * {
 *   sip_common_t        rs_common;        // Common fragment info
 *   sip_error_t        *rs_next;          // Dummy link to next
 *   uint32_t            rs_response;      // Sequence number of response
 * } sip_rseq_t;
 * @endcode
 */
Pekka Pessi's avatar
Pekka Pessi committed
191

192
msg_hclass_t sip_rseq_class[] =
Pekka Pessi's avatar
Pekka Pessi committed
193 194
SIP_HEADER_CLASS(rseq, "RSeq", "", rs_common, single, any);

195
issize_t sip_rseq_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
Pekka Pessi's avatar
Pekka Pessi committed
196 197 198 199
{
  return msg_numeric_d(home, h, s, slen);
}

200
issize_t sip_rseq_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
Pekka Pessi's avatar
Pekka Pessi committed
201 202 203 204
{
  assert(sip_is_rseq(h));
  return msg_numeric_e(b, bsiz, h, f);
}