msg_generic.c 5.4 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
 * 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
 *
 */

25
/**@internal
Pekka Pessi's avatar
Pekka Pessi committed
26
 * @ingroup msg_parser
Pekka Pessi's avatar
Pekka Pessi committed
27 28
 * @file msg_generic.c
 * @brief Functions for generic headers
29
 *
Pekka Pessi's avatar
Pekka Pessi committed
30 31 32
 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
 *
 * @date Created: Thu Jan 23 20:08:00 2003 ppessi
33
 *
Pekka Pessi's avatar
Pekka Pessi committed
34 35 36 37
 */

#include "config.h"

38
#include <sofia-sip/su_alloc.h>
Pekka Pessi's avatar
Pekka Pessi committed
39

40 41 42 43
#include "sofia-sip/msg.h"
#include "sofia-sip/bnf.h"
#include "sofia-sip/msg_parser.h"
#include "sofia-sip/msg_header.h"
Pekka Pessi's avatar
Pekka Pessi committed
44

45 46 47 48 49 50 51 52
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <stdarg.h>
#include <limits.h>

Pekka Pessi's avatar
Pekka Pessi committed
53 54 55 56 57
/**
 * Parse a generic header.
 *
 * The function msg_generic_d() parses a generic header structure.
 *
58 59 60 61
 * @param[in]     home memory home
 * @param[in,out] h    header structure
 * @param[in]     s    string to be parsed
 * @param[in]     slen length of the string
Pekka Pessi's avatar
Pekka Pessi committed
62
 *
63
 * @retval 0 when successful,
Pekka Pessi's avatar
Pekka Pessi committed
64 65
 * @retval -1 upon an error.
 */
66 67
issize_t msg_generic_d(su_home_t *home,
		       msg_header_t *h,
68
		       char *s,
69
		       isize_t slen)
Pekka Pessi's avatar
Pekka Pessi committed
70 71 72 73 74 75 76 77 78 79 80
{
  h->sh_generic->g_string = s;
  return 0;
}

/**
 * Encode a generic header.
 *
 * The function @c msg_generic_e encodes a generic header.
 *
 */
81
issize_t msg_generic_e(char b[], isize_t bsiz, msg_header_t const *h, int flags)
Pekka Pessi's avatar
Pekka Pessi committed
82
{
83
  msg_generic_t const *g = h->sh_generic;
84
  size_t n = strlen(g->g_string);
85

Pekka Pessi's avatar
Pekka Pessi committed
86 87 88
  if (bsiz > n)
    strcpy(b, g->g_string);

89
  return (issize_t)n;
Pekka Pessi's avatar
Pekka Pessi committed
90 91 92
}

/** Calculate the size of strings associated with a @c msg_generic_t object. */
93
isize_t msg_generic_dup_xtra(msg_header_t const *h, isize_t offset)
Pekka Pessi's avatar
Pekka Pessi committed
94 95 96 97 98 99 100 101 102
{
  msg_generic_t const *g = h->sh_generic;
  return offset + MSG_STRING_SIZE(g->g_string);
}

/** Duplicate one @c msg_generic_t object. */
char *msg_generic_dup_one(msg_header_t *dst,
			  msg_header_t const *src,
			  char *b,
103
			  isize_t xtra)
Pekka Pessi's avatar
Pekka Pessi committed
104 105 106
{
  char *end = b + xtra;
  MSG_STRING_DUP(b, dst->sh_generic->g_string, src->sh_generic->g_string);
107
  assert(b <= end); (void)end;
Pekka Pessi's avatar
Pekka Pessi committed
108 109 110
  return b;
}

111 112 113 114
issize_t msg_numeric_d(su_home_t *home,
		      msg_header_t *h,
		      char *s,
		      isize_t slen)
Pekka Pessi's avatar
Pekka Pessi committed
115
{
116
  msg_numeric_t *x = (msg_numeric_t *)h;
117 118
  uint32_t value = 0;
  issize_t retval = msg_uint32_d(&s, &value);
Pekka Pessi's avatar
Pekka Pessi committed
119

120 121 122
  assert(x->x_common->h_class->hc_size >= sizeof *x);

  x->x_value = value;
Pekka Pessi's avatar
Pekka Pessi committed
123 124 125 126 127 128 129

  if (*s)
    return -1;

  return retval;
}

130
issize_t msg_numeric_e(char b[], isize_t bsiz, msg_header_t const *h, int flags)
Pekka Pessi's avatar
Pekka Pessi committed
131
{
132 133 134
  msg_numeric_t *x = (msg_numeric_t *)h;

  assert(x->x_common->h_class->hc_size >= sizeof *x);
135

136
  if (x->x_value > 0xffffffffU)
137 138
    return -1;

139
  return snprintf(b, bsiz, "%lu", x->x_value);
Pekka Pessi's avatar
Pekka Pessi committed
140 141 142 143 144
}

/* ====================================================================== */
/* Comma-separated list */

145
/** @typedef struct msg_list_s msg_list_t;
146 147 148 149 150
 *
 * Type for token list headers.
 *
 */

151
issize_t msg_list_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen)
Pekka Pessi's avatar
Pekka Pessi committed
152 153 154 155
{
  return msg_commalist_d(home, &s, &h->sh_list->k_items, NULL);
}

156
issize_t msg_list_e(char b[], isize_t bsiz, msg_header_t const *h, int flags)
Pekka Pessi's avatar
Pekka Pessi committed
157 158 159
{
  int compact = MSG_IS_COMPACT(flags);
  char *b0 = b, *end = b + bsiz;
160

Pekka Pessi's avatar
Pekka Pessi committed
161 162 163 164 165 166
  MSG_COMMALIST_E(b, end, h->sh_list->k_items, compact);
  MSG_TERM_E(b, end);

  return b - b0;
}

167
/**@internal
Pekka Pessi's avatar
Pekka Pessi committed
168 169 170 171 172 173 174 175 176
 * Extra size of a msg_auth_t object.
 *
 * This function calculates extra size required by a msg_auth_t object.
 *
 * @param a pointer to a msg_auth_t object
 *
 * @return
 *   Size of strings related to msg_auth_t object.
 */
177
isize_t msg_list_dup_xtra(msg_header_t const *h, isize_t offset)
Pekka Pessi's avatar
Pekka Pessi committed
178 179 180 181 182 183 184
{
  MSG_PARAMS_SIZE(offset, h->sh_list->k_items);
  return offset;
}

char *msg_list_dup_one(msg_header_t *dst,
		       msg_header_t const *src,
185
		       char *b,
186
		       isize_t xtra)
Pekka Pessi's avatar
Pekka Pessi committed
187 188 189 190 191
{
  char *end = b + xtra;
  msg_param_t const ** items = (msg_param_t const **)&dst->sh_list->k_items;

  b = msg_params_dup(items, src->sh_list->k_items, b, xtra);
192

193
  assert(b <= end); (void)end;
Pekka Pessi's avatar
Pekka Pessi committed
194 195 196 197

  return b;
}

198 199 200 201 202
/** Append a list of constant items to a list.
 *
 * @retval 0 when successful
 * @retval -1 upon an error
 */
203 204
int msg_list_append_items(su_home_t *home,
			  msg_list_t *k,
Pekka Pessi's avatar
Pekka Pessi committed
205 206
			  msg_param_t const items[])
{
207
  size_t i;
Pekka Pessi's avatar
Pekka Pessi committed
208 209 210 211 212

  if (k == NULL) return -1;
  if (items == NULL) return 0;

  for (i = 0; items[i]; i++) {
213
    if (msg_header_add_param(home, (msg_common_t *)k, items[i]) < 0)
Pekka Pessi's avatar
Pekka Pessi committed
214 215 216 217 218 219
      return -1;
  }

  return 0;
}

220 221 222 223 224
/** Replace a list of constant items.
 *
 * @retval 0 when successful
 * @retval -1 upon an error
 */
225 226
int msg_list_replace_items(su_home_t *home,
			   msg_list_t *k,
Pekka Pessi's avatar
Pekka Pessi committed
227 228
			   msg_param_t const items[])
{
229
  size_t i;
Pekka Pessi's avatar
Pekka Pessi committed
230 231 232 233 234

  if (k == NULL) return -1;
  if (items == NULL) return 0;

  for (i = 0; items[i]; i++) {
235
    if (msg_header_replace_item(home, (msg_common_t *)k, items[i]) < 0)
Pekka Pessi's avatar
Pekka Pessi committed
236 237 238 239 240
      return -1;
  }

  return 0;
}