sl_utils_log.c 7.77 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
 * 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
 *
 */

/**@ingroup sl_utils
 *
27
 * @CFILE sl_utils_log.c
Pekka Pessi's avatar
Pekka Pessi committed
28 29 30 31 32 33 34 35 36 37
 * @brief Implementation of SIP library utility logging functions.
 *
 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
 *
 * @date Created:  Thu Oct  5 15:38:39 2000 ppessi
 */

#include "config.h"

#include <stddef.h>
38
#include <stdlib.h>
Pekka Pessi's avatar
Pekka Pessi committed
39 40 41 42
#include <string.h>
#include <stdio.h>
#include <assert.h>

43
#include <sofia-sip/su_log.h>
Pekka Pessi's avatar
Pekka Pessi committed
44

45 46
#include <sofia-sip/sip_header.h>
#include "sofia-sip/sl_utils.h"
Pekka Pessi's avatar
Pekka Pessi committed
47

48
/**Log a SIP message.
Pekka Pessi's avatar
Pekka Pessi committed
49 50 51 52
 *
 * The function sl_message_log() logs shorthand information identifying
 * the SIP message to the given @a log at level @a level.  The shorthand
 * information include the method and URL by default.  If @a details is
53
 * nonzero, topmost @Via, @CSeq, @To @b and @@From is included, too.
Pekka Pessi's avatar
Pekka Pessi committed
54 55 56 57 58 59 60 61 62
 *
 * @param log      output log (if @c NULL, su_default_log() is used).
 * @param level    log level
 * @param prefix   string logged before the first line.
 *@param sip      message to be logged.
 * @param details  flag specifying if detailed output is desired.
 */
void sl_sip_log(su_log_t *log,
		int level,
63 64
		char const *prefix,
		sip_t const *sip,
Pekka Pessi's avatar
Pekka Pessi committed
65 66 67 68 69 70 71 72
		int details)
{
  sip_cseq_t const *cs = sip->sip_cseq;

  if (log == NULL)
    log = su_log_default;

  assert(cs);
73

Pekka Pessi's avatar
Pekka Pessi committed
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
  if (sip->sip_request) {
    su_llog(log, level,
	    "%s%s "URL_FORMAT_STRING" (CSeq %d %s)\n",
	    prefix,
	    sip->sip_request->rq_method_name,
	    URL_PRINT_ARGS(sip->sip_request->rq_url),
	    cs->cs_seq,
	    cs->cs_method_name);

    if (!details)
      return;

    if (sip->sip_via) {
      char const *received = sip->sip_via->v_received;
      char const *port = sip->sip_via->v_port;

      su_llog(log, level,
	      "\tvia %s%s%s%s%s%s\n",
	      sip->sip_via->v_host,
	      port ? ":" : "", port ? port : "",
	      received ? " (" : "", received ? received : "",
	      received ? ")" : "");
    }
  }
  else {
    su_llog(log, level,
	    "%s%03u %s (CSeq %d %s)\n",
	    prefix,
	    sip->sip_status->st_status,
	    sip->sip_status->st_phrase,
	    cs->cs_seq,
	    cs->cs_method_name);
    if (!details)
      return;
  }

  if (sip->sip_from)
    sl_from_log(log, level, "\tFrom: %s\n", sip->sip_from);

  if (sip->sip_to)
    sl_to_log(log, level, "\tTo: %s\n", sip->sip_to);
}

117
/**Log a @From header.
Pekka Pessi's avatar
Pekka Pessi committed
118 119 120 121 122
 *
 * The function sl_from_log() logs the contents of @a from header to
 * the output @a log.  The @a fmt specifies the output format, where %s
 * is replaced with header contents. If @a fmt is @c NULL, only the header
 * contents are logged.
123
 *
Pekka Pessi's avatar
Pekka Pessi committed
124 125
 * @param log      output log
 * @param level    logging level of output
126
 * @param fmt      output format
127
 * @param from     @From header
Pekka Pessi's avatar
Pekka Pessi committed
128
 */
129
void sl_from_log(su_log_t *log, int level,
Pekka Pessi's avatar
Pekka Pessi committed
130 131
		 char const *fmt, sip_from_t const *from)
{
132
  sip_addr_t a[1];
Pekka Pessi's avatar
Pekka Pessi committed
133

134 135
  if (from == NULL)
    return;
Pekka Pessi's avatar
Pekka Pessi committed
136

137 138 139
  memcpy(a, from, sizeof a);
  a->a_params = NULL;
  if (!a->a_display) a->a_display = "";
140

141
  sl_header_log(log, level, fmt, (sip_header_t *)a);
Pekka Pessi's avatar
Pekka Pessi committed
142 143
}

144
/**Log a @To header.
Pekka Pessi's avatar
Pekka Pessi committed
145 146 147 148 149
 *
 * The function sl_to_log() logs the contents of @a to header to the
 * log @a log with given @a level.  The @a fmt specifies the output format,
 * where %s is replaced with header contents. If @a fmt is @c NULL, only the
 * header contents are logged.
150
 *
Pekka Pessi's avatar
Pekka Pessi committed
151 152
 * @param log      output log
 * @param level    logging level of output
153
 * @param fmt      output format
154
 * @param to       @To header
Pekka Pessi's avatar
Pekka Pessi committed
155 156 157 158 159 160
 */
void sl_to_log(su_log_t *log, int level, char const *fmt, sip_to_t const *to)
{
  sl_from_log(log, level, fmt, (sip_from_t const *)to);
}

161
/**Log a @Contact header.
Pekka Pessi's avatar
Pekka Pessi committed
162 163 164 165 166
 *
 * The function sl_contact_log() logs the contents of @a contact header
 * to the log @a log with given @a level.  The @a fmt specifies the output
 * format, where %s is replaced with header contents. If @a fmt is @c NULL,
 * only the header contents are logged.
167
 *
Pekka Pessi's avatar
Pekka Pessi committed
168 169
 * @param log      output log
 * @param level    logging level of output
170
 * @param fmt      output format
171
 * @param contact  @Contact header
Pekka Pessi's avatar
Pekka Pessi committed
172
 */
173
void sl_contact_log(su_log_t *log, int level,
Pekka Pessi's avatar
Pekka Pessi committed
174 175 176 177 178
		     char const *fmt, sip_contact_t const *m)
{
  sl_from_log(log, level, fmt, (sip_from_t const *)m);
}

179
/**Log an @Allow header(s).
Pekka Pessi's avatar
Pekka Pessi committed
180 181 182 183 184
 *
 * The function sl_allow_log() logs the contents of @a allow header to
 * the log @a log with given @a level.  The @a fmt specifies the output
 * format, where %s is replaced with header contents. If @a fmt is @c NULL,
 * only the header contents are logged.
185
 *
Pekka Pessi's avatar
Pekka Pessi committed
186 187
 * @param log      output log
 * @param level    logging level of output
188
 * @param fmt      output format
189 190
 * @param allow    @Allow header
 *
Pekka Pessi's avatar
Pekka Pessi committed
191
 */
192
void sl_allow_log(su_log_t *log, int level,
Pekka Pessi's avatar
Pekka Pessi committed
193 194
		  char const *fmt, sip_allow_t const *allow)
{
195
  sl_header_log(log, level, fmt, (sip_header_t *)allow);
Pekka Pessi's avatar
Pekka Pessi committed
196 197 198
}


199
/**Log a @Via header.
Pekka Pessi's avatar
Pekka Pessi committed
200 201 202 203 204
 *
 * The function sl_via_log() logs the contents of @a via header to
 * the @a log.  The @a fmt specifies the output format, where %s
 * is replaced with header contents. If @a fmt is @c NULL, only the header
 * contents are logged.
205
 *
206 207 208
 * @param log  output log
 * @param fmt  format used when logging
 * @param v    via header
Pekka Pessi's avatar
Pekka Pessi committed
209 210 211
 */
void sl_via_log(su_log_t *log, int level, char const *fmt, sip_via_t const *v)
{
212
  sl_header_log(log, level, fmt, (sip_header_t *)v);
Pekka Pessi's avatar
Pekka Pessi committed
213 214 215
}


216
/**Log message payload.
Pekka Pessi's avatar
Pekka Pessi committed
217 218 219 220 221 222
 *
 * The function sl_payload_log() logs the contents of @a payload object
 * to the output @a log.  Each line in the payload is prepended with the
 * @a prefix.  If @a prefix is @c NULL, only the header contents are logged.
 * For each line in payload, only first 70 charactes are logged, rest is
 * replaced with "...".
223
 *
Pekka Pessi's avatar
Pekka Pessi committed
224 225
 * @param log      output log
 * @param level    logging level of output
226
 * @param prefix   prefix appended to each payload line
Pekka Pessi's avatar
Pekka Pessi committed
227 228
 * @param pl       payload object
 */
229 230
void sl_payload_log(su_log_t *log, int level,
		    char const *prefix,
Pekka Pessi's avatar
Pekka Pessi committed
231 232 233 234 235 236 237 238 239
		    sip_payload_t const *pl)
{
  char *s = pl->pl_data, *end = pl->pl_data + pl->pl_len;
  char line[74];

  if (log == NULL)
    log = su_log_default;

  while (s < end && *s != '\0') {
240 241
    size_t n = strncspn(s, end - s, "\r\n");
    size_t crlf = strnspn(s + n, end - s - n, "\r\n");
Pekka Pessi's avatar
Pekka Pessi committed
242 243 244 245 246 247 248 249 250 251 252 253
    if (n < 70) {
      memcpy(line, s, n);
      line[n] = '\0';
    }
    else {
      memcpy(line, s, 70);
      strcpy(line + 70, "...");
    }
    su_llog(log, level, "%s%s\n", prefix, line);
    s += n + crlf;
  }
}
254

255
/** Log a header.
256 257
 *
 * Logs the contents of an header to the output @a stream. The @a fmt
258
 * specifies the output format, where %s is replaced with header contents.
259
 * If @a fmt is @c NULL, only the header contents are logged.
260
 *
261
 * @param stream   output stream
262
 * @param fmt      output format
263 264 265 266 267 268 269 270 271 272 273 274 275
 * @param h        a SIP header object
 */
void sl_header_log(su_log_t *log, int level, char const *fmt,
		   sip_header_t const *h)
{
  char *s, b[1024];
  issize_t len;

  len = sip_header_field_e(s = b, sizeof b, h, 0);
  if (len == -1)
    return;

  if ((size_t)len >= sizeof b) {
276
    s = malloc(len + 1); if (!s) return;
277
    sip_header_field_e(s, len + 1, h, 0);
278
  }
279 280 281 282 283 284 285 286 287
  s[len] = '\0';

  if (fmt == NULL)
    fmt = "%s\n";
  su_llog(log, level, fmt, s);

  if (s != b)
    free(s);
}