mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-11-13 21:17:06 +00:00
add sofia-sip 1.12.4 (plus some patches through 12/21/2006) to in tree libs
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3774 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
1 parent
0cdfa4fe13
commit
2ecac238f3
719 files changed
+311340
-2
No files matched your search
@@ -0,0 +1,53 @@
|
||||
2006-01-17 Martti Mela <martti.mela@nokia.com>
|
||||
|
||||
* msg_mime.c: defines for Mac OS X (which are lacking EBADMSG).
|
||||
|
||||
2005-11-08 Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
|
||||
* Renamed msg_test.c as test_msg.c.
|
||||
|
||||
* Renamed msg_test_class.[hc] as test_class.[hc],
|
||||
msg_test_protos.h(.in) as test_protos.h(.in),
|
||||
msg_test_table.c(.in) as test_table.c(.in).
|
||||
|
||||
2005-10-12 Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
|
||||
* Fixed msg_home() macro.
|
||||
|
||||
M ./libsofia-sip-ua/msg/msg.h -1 +1
|
||||
|
||||
2005-10-10 Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
|
||||
* Dox fix to msg_header_replace().
|
||||
|
||||
M ./libsofia-sip-ua/msg/msg_parser.c -2 +3
|
||||
|
||||
2005-08-15 Kai Vehmanen <kai.vehmanen@nokia.com>
|
||||
|
||||
* Makefile.am: Do not include msg_test_class.o in libmsg.
|
||||
|
||||
2005-08-01 Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
|
||||
* msg_mime.c: Returning -2 from msg_accept_any_d() if the list is
|
||||
empty.
|
||||
|
||||
* msg_internal.h, msg_mclass.h, msg_mclass.c, msg_parser.awk:
|
||||
|
||||
Added header-specific flags in parser table for
|
||||
msg_extract_errors().
|
||||
|
||||
* msg.h, msg.c: Added msg_extract_errors().
|
||||
|
||||
* msg_parser.c: Using header-specific flags to classify parsing
|
||||
errors with msg_extract_errors().
|
||||
|
||||
Added support for apndlist headers.
|
||||
|
||||
* msg_header.h: Added support for apndlist headers.
|
||||
|
||||
* msg_mime.c: Various Accept* headers are now apndlist meaning
|
||||
that they are printed on single line by default.
|
||||
|
||||
2005-07-18 Kai Vehmanen <kai.vehmanen@nokia.com>
|
||||
|
||||
* Initial import of the module to Sofia-SIP tree.
|
||||
@@ -0,0 +1,17 @@
|
||||
PROJECT_NAME = "msg"
|
||||
OUTPUT_DIRECTORY = ../docs/html/msg
|
||||
|
||||
INPUT = msg.docs . sofia-sip
|
||||
|
||||
@INCLUDE = ../docs/Doxyfile.conf
|
||||
@INCLUDE = ../sip/sip.doxyaliases
|
||||
|
||||
TAGFILES += ../docs/ipt.doxytags=../ipt \
|
||||
../docs/su.doxytags=../su \
|
||||
../docs/sip.doxytags=../sip \
|
||||
../docs/nta.doxytags=../nta \
|
||||
../docs/http.doxytags=../http
|
||||
|
||||
GENERATE_TAGFILE = ../docs/msg.doxytags
|
||||
|
||||
IMAGE_PATH += ../sip/images
|
||||
@@ -0,0 +1,117 @@
|
||||
#
|
||||
# Makefile.am for msg module
|
||||
#
|
||||
# Copyright (C) 2005,2006 Nokia Corporation
|
||||
# Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
# Licensed under LGPL. See file COPYING.
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Header paths
|
||||
|
||||
INCLUDES = -I$(srcdir)/../url -I../url \
|
||||
-I$(srcdir)/../bnf -I../bnf \
|
||||
-I$(srcdir)/../su -I../su
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Build targets
|
||||
|
||||
noinst_LTLIBRARIES = libmsg.la
|
||||
noinst_LIBRARIES = libtest_msg.a
|
||||
check_PROGRAMS = msg_name_hash test_msg
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Rules for building the targets
|
||||
|
||||
GENERATED_H = sofia-sip/msg_protos.h sofia-sip/msg_mime_protos.h
|
||||
PUBLIC_H = sofia-sip/msg.h sofia-sip/msg_header.h \
|
||||
sofia-sip/msg_types.h sofia-sip/msg_mclass.h \
|
||||
sofia-sip/msg_mclass_hash.h sofia-sip/msg_parser.h \
|
||||
sofia-sip/msg_addr.h sofia-sip/msg_date.h \
|
||||
sofia-sip/msg_buffer.h sofia-sip/msg_tag_class.h \
|
||||
sofia-sip/msg_mime.h
|
||||
|
||||
INTERNAL_H = msg_internal.h test_class.h
|
||||
|
||||
nobase_include_sofia_HEADERS = \
|
||||
$(GENERATED_H) $(PUBLIC_H)
|
||||
|
||||
BUILT_SOURCES = $(GENERATED_H) msg_mime_table.c test_table.c test_protos.h
|
||||
|
||||
libmsg_la_SOURCES = $(INTERNAL_H) \
|
||||
msg.c msg_tag.c \
|
||||
msg_mime.c msg_mime_table.c \
|
||||
msg_header_copy.c msg_header_make.c \
|
||||
msg_parser.c msg_mclass.c msg_parser_util.c \
|
||||
msg_basic.c msg_generic.c msg_date.c msg_auth.c
|
||||
|
||||
COVERAGE_INPUT = $(libmsg_la_SOURCES) $(include_sofia_HEADERS)
|
||||
|
||||
libtest_msg_a_SOURCES = test_class.c test_table.c test_protos.h
|
||||
|
||||
LDADD = libtest_msg.a libmsg.la \
|
||||
../bnf/libbnf.la \
|
||||
../url/liburl.la \
|
||||
../su/libsu.la
|
||||
|
||||
test_msg_LDFLAGS = -static
|
||||
|
||||
msg_name_hash_LDFLAGS = -static
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Install and distribution rules
|
||||
|
||||
dist_pkgdata_SCRIPTS = msg_parser.awk
|
||||
|
||||
EXTRA_DIST = Doxyfile msg.docs \
|
||||
sofia-sip/msg_mime_protos.h.in \
|
||||
sofia-sip/msg_protos.h.in \
|
||||
msg_mime_table.c.in \
|
||||
test_protos.h.in \
|
||||
test_table.c.in
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Tests
|
||||
|
||||
TESTS = test_msg
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Sofia specific rules
|
||||
|
||||
include ../sofia.am
|
||||
|
||||
MSG_PARSER_AWK = $(srcdir)/msg_parser.awk
|
||||
|
||||
AWK_MSG_AWK = $(AWK) -f $(MSG_PARSER_AWK)
|
||||
|
||||
test_protos.h: test_protos.h.in $(MSG_PARSER_AWK)
|
||||
test_table.c: test_table.c.in $(MSG_PARSER_AWK)
|
||||
|
||||
sofia-sip/msg_mime_protos.h: sofia-sip/msg_mime_protos.h.in
|
||||
sofia-sip/msg_protos.h: sofia-sip/msg_protos.h.in
|
||||
msg_mime_table.c: msg_mime_table.c.in $(MSG_PARSER_AWK)
|
||||
|
||||
sofia-sip/msg_mime_protos.h sofia-sip/msg_protos.h: $(MSG_PARSER_AWK)
|
||||
|
||||
test_protos.h: test_class.h
|
||||
$(AWK_MSG_AWK) module=msg_test NO_MIDDLE=1 NO_LAST=1 \
|
||||
PR=$@ TEMPLATE=$(srcdir)/test_protos.h.in $<
|
||||
|
||||
test_table.c: test_class.h
|
||||
$(AWK_MSG_AWK) module=msg_test prefix=msg \
|
||||
MC_HASH_SIZE=127 multipart=msg_multipart \
|
||||
PT=$@ TEMPLATE=$(srcdir)/test_table.c.in $<
|
||||
|
||||
sofia-sip/msg_protos.h: sofia-sip/msg_mime.h
|
||||
@-mkdir sofia-sip 2>/dev/null || true
|
||||
$(AWK_MSG_AWK) module=msg NO_FIRST=1 NO_MIDDLE=1 \
|
||||
PR=$@ TEMPLATE=$(srcdir)/sofia-sip/msg_protos.h.in $<
|
||||
|
||||
sofia-sip/msg_mime_protos.h: sofia-sip/msg_mime.h
|
||||
@-mkdir sofia-sip 2>/dev/null || true
|
||||
$(AWK_MSG_AWK) module=msg NO_FIRST=1 NO_LAST=1 \
|
||||
PR=$@ TEMPLATE=$(srcdir)/sofia-sip/msg_mime_protos.h.in $<
|
||||
|
||||
msg_mime_table.c: sofia-sip/msg_mime.h
|
||||
$(AWK_MSG_AWK) module=msg_multipart \
|
||||
tprefix=msg prefix=mp MC_HASH_SIZE=127 \
|
||||
PT=$@ TEMPLATE=$(srcdir)/msg_mime_table.c.in $<
|
||||
@@ -0,0 +1,830 @@
|
||||
# Makefile.in generated by automake 1.9.2 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
#
|
||||
# Makefile.am for msg module
|
||||
#
|
||||
# Copyright (C) 2005,2006 Nokia Corporation
|
||||
# Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
# Licensed under LGPL. See file COPYING.
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Header paths
|
||||
|
||||
# common Makefile targets for libsofia-sip-ua modules
|
||||
# ---------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
SOURCES = $(libtest_msg_a_SOURCES) $(libmsg_la_SOURCES) msg_name_hash.c test_msg.c
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
top_builddir = ../..
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
INSTALL = @INSTALL@
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
target_triplet = @target@
|
||||
check_PROGRAMS = msg_name_hash$(EXEEXT) test_msg$(EXEEXT)
|
||||
DIST_COMMON = $(dist_pkgdata_SCRIPTS) $(nobase_include_sofia_HEADERS) \
|
||||
$(srcdir)/../sofia.am $(srcdir)/Makefile.am \
|
||||
$(srcdir)/Makefile.in ChangeLog
|
||||
subdir = libsofia-sip-ua/msg
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \
|
||||
$(top_srcdir)/m4/sac-openssl.m4 $(top_srcdir)/m4/sac-su.m4 \
|
||||
$(top_srcdir)/m4/sac-su2.m4 $(top_srcdir)/m4/sac-tport.m4 \
|
||||
$(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h \
|
||||
$(top_builddir)/libsofia-sip-ua/su/sofia-sip/su_configure.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
LIBRARIES = $(noinst_LIBRARIES)
|
||||
ARFLAGS = cru
|
||||
libtest_msg_a_AR = $(AR) $(ARFLAGS)
|
||||
libtest_msg_a_LIBADD =
|
||||
am_libtest_msg_a_OBJECTS = test_class.$(OBJEXT) test_table.$(OBJEXT)
|
||||
libtest_msg_a_OBJECTS = $(am_libtest_msg_a_OBJECTS)
|
||||
LTLIBRARIES = $(noinst_LTLIBRARIES)
|
||||
libmsg_la_LIBADD =
|
||||
am__objects_1 =
|
||||
am_libmsg_la_OBJECTS = $(am__objects_1) msg.lo msg_tag.lo msg_mime.lo \
|
||||
msg_mime_table.lo msg_header_copy.lo msg_header_make.lo \
|
||||
msg_parser.lo msg_mclass.lo msg_parser_util.lo msg_basic.lo \
|
||||
msg_generic.lo msg_date.lo msg_auth.lo
|
||||
libmsg_la_OBJECTS = $(am_libmsg_la_OBJECTS)
|
||||
msg_name_hash_SOURCES = msg_name_hash.c
|
||||
msg_name_hash_OBJECTS = msg_name_hash.$(OBJEXT)
|
||||
msg_name_hash_LDADD = $(LDADD)
|
||||
msg_name_hash_DEPENDENCIES = libtest_msg.a libmsg.la ../bnf/libbnf.la \
|
||||
../url/liburl.la ../su/libsu.la
|
||||
test_msg_SOURCES = test_msg.c
|
||||
test_msg_OBJECTS = test_msg.$(OBJEXT)
|
||||
test_msg_LDADD = $(LDADD)
|
||||
test_msg_DEPENDENCIES = libtest_msg.a libmsg.la ../bnf/libbnf.la \
|
||||
../url/liburl.la ../su/libsu.la
|
||||
am__installdirs = "$(DESTDIR)$(pkgdatadir)" \
|
||||
"$(DESTDIR)$(include_sofiadir)"
|
||||
dist_pkgdataSCRIPT_INSTALL = $(INSTALL_SCRIPT)
|
||||
SCRIPTS = $(dist_pkgdata_SCRIPTS)
|
||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -I$(top_builddir)/libsofia-sip-ua/su/sofia-sip
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) --mode=compile --tag=CC $(CC) $(DEFS) \
|
||||
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||
$(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) --mode=link --tag=CC $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
SOURCES = $(libtest_msg_a_SOURCES) $(libmsg_la_SOURCES) \
|
||||
msg_name_hash.c test_msg.c
|
||||
DIST_SOURCES = $(libtest_msg_a_SOURCES) $(libmsg_la_SOURCES) \
|
||||
msg_name_hash.c test_msg.c
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
|
||||
nobase_include_sofiaHEADERS_INSTALL = $(install_sh_DATA)
|
||||
HEADERS = $(nobase_include_sofia_HEADERS)
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
|
||||
AMDEP_FALSE = @AMDEP_FALSE@
|
||||
AMDEP_TRUE = @AMDEP_TRUE@
|
||||
AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
COREFOUNDATION_FALSE = @COREFOUNDATION_FALSE@
|
||||
COREFOUNDATION_TRUE = @COREFOUNDATION_TRUE@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CWFLAG = @CWFLAG@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DOXYGEN = @DOXYGEN@
|
||||
ECHO = @ECHO@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
ENABLE_COVERAGE_FALSE = @ENABLE_COVERAGE_FALSE@
|
||||
ENABLE_COVERAGE_TRUE = @ENABLE_COVERAGE_TRUE@
|
||||
ETAGS = @ETAGS@
|
||||
EXEEXT = @EXEEXT@
|
||||
EXPENSIVE_CHECKS_FALSE = @EXPENSIVE_CHECKS_FALSE@
|
||||
EXPENSIVE_CHECKS_TRUE = @EXPENSIVE_CHECKS_TRUE@
|
||||
F77 = @F77@
|
||||
FFLAGS = @FFLAGS@
|
||||
GLIB_CFLAGS = @GLIB_CFLAGS@
|
||||
GLIB_LIBS = @GLIB_LIBS@
|
||||
GLIB_VERSION = @GLIB_VERSION@
|
||||
HAVE_DOXYGEN_FALSE = @HAVE_DOXYGEN_FALSE@
|
||||
HAVE_DOXYGEN_TRUE = @HAVE_DOXYGEN_TRUE@
|
||||
HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@
|
||||
HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@
|
||||
HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@
|
||||
HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@
|
||||
HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@
|
||||
HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@
|
||||
HAVE_TLS_FALSE = @HAVE_TLS_FALSE@
|
||||
HAVE_TLS_TRUE = @HAVE_TLS_TRUE@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIBVER_SOFIA_SIP_UA_AGE = @LIBVER_SOFIA_SIP_UA_AGE@
|
||||
LIBVER_SOFIA_SIP_UA_CUR = @LIBVER_SOFIA_SIP_UA_CUR@
|
||||
LIBVER_SOFIA_SIP_UA_GLIB_AGE = @LIBVER_SOFIA_SIP_UA_GLIB_AGE@
|
||||
LIBVER_SOFIA_SIP_UA_GLIB_CUR = @LIBVER_SOFIA_SIP_UA_GLIB_CUR@
|
||||
LIBVER_SOFIA_SIP_UA_GLIB_REV = @LIBVER_SOFIA_SIP_UA_GLIB_REV@
|
||||
LIBVER_SOFIA_SIP_UA_GLIB_SOVER = @LIBVER_SOFIA_SIP_UA_GLIB_SOVER@
|
||||
LIBVER_SOFIA_SIP_UA_REV = @LIBVER_SOFIA_SIP_UA_REV@
|
||||
LIBVER_SOFIA_SIP_UA_SOVER = @LIBVER_SOFIA_SIP_UA_SOVER@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAINT = @MAINT@
|
||||
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
|
||||
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MINGW_ENVIRONMENT = @MINGW_ENVIRONMENT@
|
||||
MOSTLYCLEANFILES = @MOSTLYCLEANFILES@
|
||||
NDEBUG_FALSE = @NDEBUG_FALSE@
|
||||
NDEBUG_TRUE = @NDEBUG_TRUE@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PKG_CONFIG = @PKG_CONFIG@
|
||||
RANLIB = @RANLIB@
|
||||
REPLACE_LIBADD = @REPLACE_LIBADD@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SOFIA_CFLAGS = @SOFIA_CFLAGS@
|
||||
SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@
|
||||
STRIP = @STRIP@
|
||||
TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@
|
||||
VERSION = @VERSION@
|
||||
VER_LIBSOFIA_SIP_UA_MAJOR_MINOR = @VER_LIBSOFIA_SIP_UA_MAJOR_MINOR@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_F77 = @ac_ct_F77@
|
||||
ac_ct_LD = @ac_ct_LD@
|
||||
ac_ct_RANLIB = @ac_ct_RANLIB@
|
||||
ac_ct_STRIP = @ac_ct_STRIP@
|
||||
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
|
||||
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
|
||||
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
|
||||
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
datadir = @datadir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
include_sofiadir = @include_sofiadir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target = @target@
|
||||
target_alias = @target_alias@
|
||||
target_cpu = @target_cpu@
|
||||
target_os = @target_os@
|
||||
target_vendor = @target_vendor@
|
||||
INCLUDES = -I$(srcdir)/../url -I../url \
|
||||
-I$(srcdir)/../bnf -I../bnf \
|
||||
-I$(srcdir)/../su -I../su
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Build targets
|
||||
noinst_LTLIBRARIES = libmsg.la
|
||||
noinst_LIBRARIES = libtest_msg.a
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Rules for building the targets
|
||||
GENERATED_H = sofia-sip/msg_protos.h sofia-sip/msg_mime_protos.h
|
||||
PUBLIC_H = sofia-sip/msg.h sofia-sip/msg_header.h \
|
||||
sofia-sip/msg_types.h sofia-sip/msg_mclass.h \
|
||||
sofia-sip/msg_mclass_hash.h sofia-sip/msg_parser.h \
|
||||
sofia-sip/msg_addr.h sofia-sip/msg_date.h \
|
||||
sofia-sip/msg_buffer.h sofia-sip/msg_tag_class.h \
|
||||
sofia-sip/msg_mime.h
|
||||
|
||||
INTERNAL_H = msg_internal.h test_class.h
|
||||
nobase_include_sofia_HEADERS = \
|
||||
$(GENERATED_H) $(PUBLIC_H)
|
||||
|
||||
BUILT_SOURCES = $(GENERATED_H) msg_mime_table.c test_table.c test_protos.h
|
||||
libmsg_la_SOURCES = $(INTERNAL_H) \
|
||||
msg.c msg_tag.c \
|
||||
msg_mime.c msg_mime_table.c \
|
||||
msg_header_copy.c msg_header_make.c \
|
||||
msg_parser.c msg_mclass.c msg_parser_util.c \
|
||||
msg_basic.c msg_generic.c msg_date.c msg_auth.c
|
||||
|
||||
COVERAGE_INPUT = $(libmsg_la_SOURCES) $(include_sofia_HEADERS)
|
||||
libtest_msg_a_SOURCES = test_class.c test_table.c test_protos.h
|
||||
LDADD = libtest_msg.a libmsg.la \
|
||||
../bnf/libbnf.la \
|
||||
../url/liburl.la \
|
||||
../su/libsu.la
|
||||
|
||||
test_msg_LDFLAGS = -static
|
||||
msg_name_hash_LDFLAGS = -static
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Install and distribution rules
|
||||
dist_pkgdata_SCRIPTS = msg_parser.awk
|
||||
EXTRA_DIST = Doxyfile msg.docs \
|
||||
sofia-sip/msg_mime_protos.h.in \
|
||||
sofia-sip/msg_protos.h.in \
|
||||
msg_mime_table.c.in \
|
||||
test_protos.h.in \
|
||||
test_table.c.in
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Tests
|
||||
TESTS = test_msg
|
||||
AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS)
|
||||
DISTCLEANFILES = $(BUILT_SOURCES)
|
||||
|
||||
# rules for building tag files
|
||||
TAG_AWK = $(top_srcdir)/libsofia-sip-ua/su/tag_dll.awk
|
||||
INTERNAL_INCLUDES = \
|
||||
-I$(srcdir)/../features -I../features \
|
||||
-I$(srcdir)/../ipt -I../ipt \
|
||||
-I$(srcdir)/../iptsec -I../iptsec \
|
||||
-I$(srcdir)/../bnf -I../bnf \
|
||||
-I$(srcdir)/../http -I../http \
|
||||
-I$(srcdir)/../msg -I../msg \
|
||||
-I$(srcdir)/../nth -I../nth \
|
||||
-I$(srcdir)/../nta -I../nta \
|
||||
-I$(srcdir)/../nea -I../nea \
|
||||
-I$(srcdir)/../nua -I../nua \
|
||||
-I$(srcdir)/../soa -I../soa \
|
||||
-I$(srcdir)/../sdp -I../sdp \
|
||||
-I$(srcdir)/../sip -I../sip \
|
||||
-I$(srcdir)/../soa -I../soa \
|
||||
-I$(srcdir)/../sresolv -I../sresolv \
|
||||
-I$(srcdir)/../tport -I../tport \
|
||||
-I$(srcdir)/../stun -I../stun \
|
||||
-I$(srcdir)/../url -I../url \
|
||||
-I$(srcdir)/../su -I../su
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Sofia specific rules
|
||||
MSG_PARSER_AWK = $(srcdir)/msg_parser.awk
|
||||
AWK_MSG_AWK = $(AWK) -f $(MSG_PARSER_AWK)
|
||||
all: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .lo .o .obj
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libsofia-sip-ua/msg/Makefile'; \
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu libsofia-sip-ua/msg/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
clean-noinstLIBRARIES:
|
||||
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
|
||||
libtest_msg.a: $(libtest_msg_a_OBJECTS) $(libtest_msg_a_DEPENDENCIES)
|
||||
-rm -f libtest_msg.a
|
||||
$(libtest_msg_a_AR) libtest_msg.a $(libtest_msg_a_OBJECTS) $(libtest_msg_a_LIBADD)
|
||||
$(RANLIB) libtest_msg.a
|
||||
|
||||
clean-noinstLTLIBRARIES:
|
||||
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
|
||||
@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
|
||||
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
|
||||
test "$$dir" != "$$p" || dir=.; \
|
||||
echo "rm -f \"$${dir}/so_locations\""; \
|
||||
rm -f "$${dir}/so_locations"; \
|
||||
done
|
||||
libmsg.la: $(libmsg_la_OBJECTS) $(libmsg_la_DEPENDENCIES)
|
||||
$(LINK) $(libmsg_la_LDFLAGS) $(libmsg_la_OBJECTS) $(libmsg_la_LIBADD) $(LIBS)
|
||||
|
||||
clean-checkPROGRAMS:
|
||||
@list='$(check_PROGRAMS)'; for p in $$list; do \
|
||||
f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
|
||||
echo " rm -f $$p $$f"; \
|
||||
rm -f $$p $$f ; \
|
||||
done
|
||||
msg_name_hash$(EXEEXT): $(msg_name_hash_OBJECTS) $(msg_name_hash_DEPENDENCIES)
|
||||
@rm -f msg_name_hash$(EXEEXT)
|
||||
$(LINK) $(msg_name_hash_LDFLAGS) $(msg_name_hash_OBJECTS) $(msg_name_hash_LDADD) $(LIBS)
|
||||
test_msg$(EXEEXT): $(test_msg_OBJECTS) $(test_msg_DEPENDENCIES)
|
||||
@rm -f test_msg$(EXEEXT)
|
||||
$(LINK) $(test_msg_LDFLAGS) $(test_msg_OBJECTS) $(test_msg_LDADD) $(LIBS)
|
||||
install-dist_pkgdataSCRIPTS: $(dist_pkgdata_SCRIPTS)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(pkgdatadir)" || $(mkdir_p) "$(DESTDIR)$(pkgdatadir)"
|
||||
@list='$(dist_pkgdata_SCRIPTS)'; for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
if test -f $$d$$p; then \
|
||||
f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
|
||||
echo " $(dist_pkgdataSCRIPT_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgdatadir)/$$f'"; \
|
||||
$(dist_pkgdataSCRIPT_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgdatadir)/$$f"; \
|
||||
else :; fi; \
|
||||
done
|
||||
|
||||
uninstall-dist_pkgdataSCRIPTS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(dist_pkgdata_SCRIPTS)'; for p in $$list; do \
|
||||
f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
|
||||
echo " rm -f '$(DESTDIR)$(pkgdatadir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(pkgdatadir)/$$f"; \
|
||||
done
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_auth.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_basic.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_date.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_generic.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_header_copy.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_header_make.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_mclass.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_mime.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_mime_table.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_name_hash.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_parser.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_parser_util.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg_tag.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_class.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_msg.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_table.Po@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
|
||||
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
|
||||
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
distclean-libtool:
|
||||
-rm -f libtool
|
||||
uninstall-info-am:
|
||||
install-nobase_include_sofiaHEADERS: $(nobase_include_sofia_HEADERS)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(include_sofiadir)" || $(mkdir_p) "$(DESTDIR)$(include_sofiadir)"
|
||||
@$(am__vpath_adj_setup) \
|
||||
list='$(nobase_include_sofia_HEADERS)'; for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
$(am__vpath_adj) \
|
||||
echo " $(nobase_include_sofiaHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(include_sofiadir)/$$f'"; \
|
||||
$(nobase_include_sofiaHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(include_sofiadir)/$$f"; \
|
||||
done
|
||||
|
||||
uninstall-nobase_include_sofiaHEADERS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@$(am__vpath_adj_setup) \
|
||||
list='$(nobase_include_sofia_HEADERS)'; for p in $$list; do \
|
||||
$(am__vpath_adj) \
|
||||
echo " rm -f '$(DESTDIR)$(include_sofiadir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(include_sofiadir)/$$f"; \
|
||||
done
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$tags $$unique; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& cd $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) $$here
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
check-TESTS: $(TESTS)
|
||||
@failed=0; all=0; xfail=0; xpass=0; skip=0; \
|
||||
srcdir=$(srcdir); export srcdir; \
|
||||
list='$(TESTS)'; \
|
||||
if test -n "$$list"; then \
|
||||
for tst in $$list; do \
|
||||
if test -f ./$$tst; then dir=./; \
|
||||
elif test -f $$tst; then dir=; \
|
||||
else dir="$(srcdir)/"; fi; \
|
||||
if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
|
||||
all=`expr $$all + 1`; \
|
||||
case " $(XFAIL_TESTS) " in \
|
||||
*" $$tst "*) \
|
||||
xpass=`expr $$xpass + 1`; \
|
||||
failed=`expr $$failed + 1`; \
|
||||
echo "XPASS: $$tst"; \
|
||||
;; \
|
||||
*) \
|
||||
echo "PASS: $$tst"; \
|
||||
;; \
|
||||
esac; \
|
||||
elif test $$? -ne 77; then \
|
||||
all=`expr $$all + 1`; \
|
||||
case " $(XFAIL_TESTS) " in \
|
||||
*" $$tst "*) \
|
||||
xfail=`expr $$xfail + 1`; \
|
||||
echo "XFAIL: $$tst"; \
|
||||
;; \
|
||||
*) \
|
||||
failed=`expr $$failed + 1`; \
|
||||
echo "FAIL: $$tst"; \
|
||||
;; \
|
||||
esac; \
|
||||
else \
|
||||
skip=`expr $$skip + 1`; \
|
||||
echo "SKIP: $$tst"; \
|
||||
fi; \
|
||||
done; \
|
||||
if test "$$failed" -eq 0; then \
|
||||
if test "$$xfail" -eq 0; then \
|
||||
banner="All $$all tests passed"; \
|
||||
else \
|
||||
banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
|
||||
fi; \
|
||||
else \
|
||||
if test "$$xpass" -eq 0; then \
|
||||
banner="$$failed of $$all tests failed"; \
|
||||
else \
|
||||
banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
|
||||
fi; \
|
||||
fi; \
|
||||
dashes="$$banner"; \
|
||||
skipped=""; \
|
||||
if test "$$skip" -ne 0; then \
|
||||
skipped="($$skip tests were not run)"; \
|
||||
test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
|
||||
dashes="$$skipped"; \
|
||||
fi; \
|
||||
report=""; \
|
||||
if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
|
||||
report="Please report to $(PACKAGE_BUGREPORT)"; \
|
||||
test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
|
||||
dashes="$$report"; \
|
||||
fi; \
|
||||
dashes=`echo "$$dashes" | sed s/./=/g`; \
|
||||
echo "$$dashes"; \
|
||||
echo "$$banner"; \
|
||||
test -z "$$skipped" || echo "$$skipped"; \
|
||||
test -z "$$report" || echo "$$report"; \
|
||||
echo "$$dashes"; \
|
||||
test "$$failed" -eq 0; \
|
||||
else :; fi
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
$(mkdir_p) $(distdir)/.. $(distdir)/sofia-sip
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
|
||||
list='$(DISTFILES)'; for file in $$list; do \
|
||||
case $$file in \
|
||||
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
|
||||
esac; \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
||||
dir="/$$dir"; \
|
||||
$(mkdir_p) "$(distdir)$$dir"; \
|
||||
else \
|
||||
dir=''; \
|
||||
fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
|
||||
$(MAKE) $(AM_MAKEFLAGS) check-TESTS
|
||||
check: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) check-am
|
||||
all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) $(SCRIPTS) $(HEADERS)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(include_sofiadir)"; do \
|
||||
test -z "$$dir" || $(mkdir_p) "$$dir"; \
|
||||
done
|
||||
install: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
|
||||
clean-noinstLIBRARIES clean-noinstLTLIBRARIES mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-libtool distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am: install-dist_pkgdataSCRIPTS \
|
||||
install-nobase_include_sofiaHEADERS
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-man:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-dist_pkgdataSCRIPTS uninstall-info-am \
|
||||
uninstall-nobase_include_sofiaHEADERS
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
|
||||
clean-checkPROGRAMS clean-generic clean-libtool \
|
||||
clean-noinstLIBRARIES clean-noinstLTLIBRARIES ctags distclean \
|
||||
distclean-compile distclean-generic distclean-libtool \
|
||||
distclean-tags distdir dvi dvi-am html html-am info info-am \
|
||||
install install-am install-data install-data-am \
|
||||
install-dist_pkgdataSCRIPTS install-exec install-exec-am \
|
||||
install-info install-info-am install-man \
|
||||
install-nobase_include_sofiaHEADERS install-strip installcheck \
|
||||
installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
|
||||
tags uninstall uninstall-am uninstall-dist_pkgdataSCRIPTS \
|
||||
uninstall-info-am uninstall-nobase_include_sofiaHEADERS
|
||||
|
||||
|
||||
built-sources: $(BUILT_SOURCES)
|
||||
|
||||
clean-built-sources:
|
||||
-rm -rf $(BUILT_SOURCES) $(BUILT_SOURCES:%=$(srcdir)/%)
|
||||
|
||||
*_tag_ref.c: $(TAG_AWK)
|
||||
|
||||
%_tag_ref.c: %_tag.c
|
||||
$(AWK) -f $(TAG_AWK) NODLL=1 $(TAG_DLL_FLAGS) $<
|
||||
|
||||
@ENABLE_COVERAGE_TRUE@coverage:
|
||||
@ENABLE_COVERAGE_TRUE@ @$(top_srcdir)/scripts/coverage $(COVERAGE_FLAGS) $(COVERAGE_INPUT)
|
||||
|
||||
../bnf/libbnf.la ../http/libhttp.la ../ipt/libipt.la ../iptsec/libiptsec.la \
|
||||
../msg/libmsg.la ../nea/libnea.la ../nta/libnta.la ../nth/libnth.la \
|
||||
../nua/libnua.la ../sdp/libsdp.la ../sip/libsip.la ../soa/libsoa.la \
|
||||
../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \
|
||||
../tport/libtport.la ../url/liburl.la:
|
||||
$(MAKE) -C $(@D) $(@F)
|
||||
|
||||
test_protos.h: test_protos.h.in $(MSG_PARSER_AWK)
|
||||
test_table.c: test_table.c.in $(MSG_PARSER_AWK)
|
||||
|
||||
sofia-sip/msg_mime_protos.h: sofia-sip/msg_mime_protos.h.in
|
||||
sofia-sip/msg_protos.h: sofia-sip/msg_protos.h.in
|
||||
msg_mime_table.c: msg_mime_table.c.in $(MSG_PARSER_AWK)
|
||||
|
||||
sofia-sip/msg_mime_protos.h sofia-sip/msg_protos.h: $(MSG_PARSER_AWK)
|
||||
|
||||
test_protos.h: test_class.h
|
||||
$(AWK_MSG_AWK) module=msg_test NO_MIDDLE=1 NO_LAST=1 \
|
||||
PR=$@ TEMPLATE=$(srcdir)/test_protos.h.in $<
|
||||
|
||||
test_table.c: test_class.h
|
||||
$(AWK_MSG_AWK) module=msg_test prefix=msg \
|
||||
MC_HASH_SIZE=127 multipart=msg_multipart \
|
||||
PT=$@ TEMPLATE=$(srcdir)/test_table.c.in $<
|
||||
|
||||
sofia-sip/msg_protos.h: sofia-sip/msg_mime.h
|
||||
@-mkdir sofia-sip 2>/dev/null || true
|
||||
$(AWK_MSG_AWK) module=msg NO_FIRST=1 NO_MIDDLE=1 \
|
||||
PR=$@ TEMPLATE=$(srcdir)/sofia-sip/msg_protos.h.in $<
|
||||
|
||||
sofia-sip/msg_mime_protos.h: sofia-sip/msg_mime.h
|
||||
@-mkdir sofia-sip 2>/dev/null || true
|
||||
$(AWK_MSG_AWK) module=msg NO_FIRST=1 NO_LAST=1 \
|
||||
PR=$@ TEMPLATE=$(srcdir)/sofia-sip/msg_mime_protos.h.in $<
|
||||
|
||||
msg_mime_table.c: sofia-sip/msg_mime.h
|
||||
$(AWK_MSG_AWK) module=msg_multipart \
|
||||
tprefix=msg prefix=mp MC_HASH_SIZE=127 \
|
||||
PT=$@ TEMPLATE=$(srcdir)/msg_mime_table.c.in $<
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
@@ -0,0 +1,409 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
/**@file msg.c Message object implementation.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Thu Jun 8 19:28:55 2000 ppessi
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <sofia-sip/su_alloc.h> /* XXX */
|
||||
#include <sofia-sip/su.h>
|
||||
|
||||
#include "msg_internal.h"
|
||||
#include "sofia-sip/msg_parser.h"
|
||||
#include "sofia-sip/msg_mclass.h"
|
||||
|
||||
/**
|
||||
* Create a message.
|
||||
*
|
||||
* @relatesalso msg_s
|
||||
*
|
||||
* @param mc message class
|
||||
* @param flags message control flags
|
||||
*/
|
||||
msg_t *msg_create(msg_mclass_t const *mc, int flags)
|
||||
{
|
||||
msg_t *msg = su_home_new(sizeof(*msg) + mc->mc_msize);
|
||||
|
||||
if (msg) {
|
||||
if ((flags & MSG_FLG_THRDSAFE) &&
|
||||
su_home_threadsafe(msg->m_home) < 0) {
|
||||
su_home_unref(msg->m_home);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
msg->m_refs++;
|
||||
msg->m_tail = &msg->m_chain;
|
||||
msg->m_addrinfo.ai_addrlen = sizeof(msg->m_addr);
|
||||
msg->m_addrinfo.ai_addr = &msg->m_addr->su_sa;
|
||||
msg->m_maxsize = 0;
|
||||
|
||||
flags &= MSG_FLG_USERMASK;
|
||||
|
||||
msg->m_class = mc;
|
||||
msg->m_oflags = flags;
|
||||
msg->m_object = (void *)(msg + 1);
|
||||
msg->m_object->msg_size = mc->mc_msize;
|
||||
msg->m_object->msg_flags = mc->mc_flags | flags;
|
||||
msg->m_object->msg_common->h_class = (void *)mc;
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**Increment a message reference count.
|
||||
*
|
||||
* @relatesalso msg_s
|
||||
*
|
||||
* Creates a reference to a message. The
|
||||
* referenced message is not freed until all the references have been
|
||||
* destroyed.
|
||||
*
|
||||
* @param msg message of which a reference is created
|
||||
*
|
||||
* @return
|
||||
* A pointer to a message.
|
||||
*/
|
||||
msg_t *msg_ref_create(msg_t *msg)
|
||||
{
|
||||
if (msg) {
|
||||
su_home_mutex_lock(msg->m_home);
|
||||
msg->m_refs++;
|
||||
su_home_mutex_unlock(msg->m_home);
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**Set a message parent.
|
||||
*
|
||||
* @relatesalso msg_s
|
||||
*
|
||||
* Set a parent for a message. The parent message is not destroyed until all
|
||||
* its kids have been destroyed - each kid keeps a reference to its parent
|
||||
* message.
|
||||
*
|
||||
* @param kid child message
|
||||
* @param dad parent message
|
||||
*/
|
||||
void msg_set_parent(msg_t *kid, msg_t *dad)
|
||||
{
|
||||
if (kid) {
|
||||
msg_t *step_dad = kid->m_parent;
|
||||
|
||||
if (dad && step_dad && step_dad != dad)
|
||||
msg_ref_destroy(step_dad);
|
||||
|
||||
kid->m_parent = msg_ref_create(dad);
|
||||
}
|
||||
}
|
||||
|
||||
/** Destroy a reference to a message.
|
||||
*
|
||||
* @relatesalso msg_s
|
||||
*
|
||||
* @param ref pointer to msg object
|
||||
*
|
||||
* @deprecated Use msg_destroy() instead.
|
||||
*/
|
||||
void msg_ref_destroy(msg_t *ref)
|
||||
{
|
||||
msg_destroy(ref);
|
||||
}
|
||||
|
||||
/**Deinitialize and free a message.
|
||||
*
|
||||
* @relatesalso msg_s
|
||||
*
|
||||
* @param msg message to be destroyed
|
||||
*/
|
||||
void msg_destroy(msg_t *msg)
|
||||
{
|
||||
msg_t *parent;
|
||||
|
||||
for (; msg; msg = parent) {
|
||||
int refs;
|
||||
su_home_mutex_lock(msg->m_home);
|
||||
parent = msg->m_parent;
|
||||
if (msg->m_refs)
|
||||
msg->m_refs--;
|
||||
refs = msg->m_refs;
|
||||
su_home_mutex_unlock(msg->m_home);
|
||||
if (refs)
|
||||
break;
|
||||
su_home_zap(msg->m_home);
|
||||
}
|
||||
}
|
||||
|
||||
/* Message object routines */
|
||||
|
||||
/**Retrieve public message structure.
|
||||
*
|
||||
* Get a pointer to the public message structure.
|
||||
*
|
||||
* @param msg pointer to msg object
|
||||
*
|
||||
* @returns
|
||||
* A pointer to the public message structure, or NULL if none.
|
||||
*/
|
||||
msg_pub_t *msg_object(msg_t const *msg)
|
||||
{
|
||||
if (msg)
|
||||
return msg->m_object;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**Retrieve public message structure of given type.
|
||||
*
|
||||
* @relatesalso msg_s
|
||||
*
|
||||
* Get a pointer to the public message structure of the
|
||||
* given protocol.
|
||||
*
|
||||
* @param msg pointer to msg object
|
||||
* @param tag tag of public message structure
|
||||
*
|
||||
* @returns
|
||||
* A pointer to the public message structure, or NULL if there is none or
|
||||
* the message is not for desired protocol.
|
||||
*/
|
||||
msg_pub_t *msg_public(msg_t const *msg, void *tag)
|
||||
{
|
||||
if (msg && msg->m_class->mc_tag == tag)
|
||||
return msg->m_object;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**Retrieve message class.
|
||||
*
|
||||
* @relatesalso msg_s
|
||||
*
|
||||
* Get a pointer to the message class object
|
||||
* (factory object for the message).
|
||||
*
|
||||
* @param msg pointer to msg object
|
||||
*
|
||||
* @returns
|
||||
* A pointer to the message class, or NULL if none.
|
||||
*/
|
||||
msg_mclass_t const *msg_mclass(msg_t const *msg)
|
||||
{
|
||||
if (msg)
|
||||
return msg->m_class;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Address management */
|
||||
|
||||
/** Zero the message address.
|
||||
*
|
||||
* @relatesalso msg_s
|
||||
*
|
||||
* Zero the address and addressinfo structures associated with the message.
|
||||
*
|
||||
* @sa msg_addrinfo(), msg_set_address(), msg_get_address(), msg_addr_copy().
|
||||
*/
|
||||
void msg_addr_zero(msg_t *msg)
|
||||
{
|
||||
memset(&msg->m_addr, 0, sizeof(&msg->m_addr));
|
||||
memset(&msg->m_addrinfo, 0, sizeof(&msg->m_addrinfo));
|
||||
|
||||
msg->m_addrinfo.ai_addrlen = sizeof(msg->m_addr);
|
||||
msg->m_addrinfo.ai_addr = &msg->m_addr->su_sa;
|
||||
}
|
||||
|
||||
/** Get pointer to socket address structure.
|
||||
*
|
||||
* @relatesalso msg_s
|
||||
*
|
||||
* @deprecated Use msg_get_address() or msg_set_address() instead.
|
||||
*/
|
||||
su_sockaddr_t *msg_addr(msg_t *msg)
|
||||
{
|
||||
return msg ? msg->m_addr : 0;
|
||||
}
|
||||
|
||||
/** Get message address.
|
||||
*
|
||||
* @relatesalso msg_s
|
||||
*
|
||||
* Copy the socket address associated with the message to the supplied
|
||||
* socket address struture.
|
||||
*
|
||||
* @param msg pointer to msg object
|
||||
* @param su pointer to socket address structure
|
||||
* @param return_len return parameter value for length
|
||||
* of socket address structure
|
||||
*
|
||||
* @sa msg_addrinfo(), msg_set_address(), msg_addr_zero(), msg_addr_copy().
|
||||
*/
|
||||
int msg_get_address(msg_t *msg, su_sockaddr_t *su, socklen_t *return_len)
|
||||
{
|
||||
if (msg && return_len && *return_len >= msg->m_addrinfo.ai_addrlen) {
|
||||
*return_len = (socklen_t)msg->m_addrinfo.ai_addrlen;
|
||||
if (su)
|
||||
memcpy(su, msg->m_addr, msg->m_addrinfo.ai_addrlen);
|
||||
return 0;
|
||||
}
|
||||
if (msg)
|
||||
msg->m_errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Set message address.
|
||||
*
|
||||
* @relatesalso msg_s
|
||||
*
|
||||
* Copy the supplied socket address to the socket address structure
|
||||
* associated with the message.
|
||||
*
|
||||
* @param msg pointer to msg object
|
||||
* @param su pointer to socket address structure
|
||||
* @param sulen length of socket address structure
|
||||
*
|
||||
* @sa msg_addrinfo(), msg_get_address(), msg_addr_zero(), msg_addr_copy().
|
||||
*/
|
||||
int msg_set_address(msg_t *msg, su_sockaddr_t const *su, socklen_t sulen)
|
||||
{
|
||||
if (sulen < (sizeof msg->m_addr) && msg && su) {
|
||||
memcpy(msg->m_addr, su, msg->m_addrinfo.ai_addrlen = sulen);
|
||||
msg->m_addrinfo.ai_family = su->su_family;
|
||||
return 0;
|
||||
}
|
||||
if (msg)
|
||||
msg->m_errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Get addrinfo structure.
|
||||
*
|
||||
* @relatesalso msg_s
|
||||
*
|
||||
* Get pointer to the addrinfo structure associated with the message.
|
||||
*
|
||||
* @param msg pointer to msg object
|
||||
*
|
||||
* @retval pointer to addrinfo structure
|
||||
* @retval NULL if msg is NULL
|
||||
*
|
||||
* @sa msg_get_address(), msg_set_address(), msg_addr_zero(), msg_addr_copy().
|
||||
*/
|
||||
su_addrinfo_t *msg_addrinfo(msg_t *msg)
|
||||
{
|
||||
return msg ? &msg->m_addrinfo : 0;
|
||||
}
|
||||
|
||||
/**Copy message address.
|
||||
*
|
||||
* @relatesalso msg_s
|
||||
*
|
||||
* Copy the addrinfo and socket address structures from @a src to the @a dst
|
||||
* message object.
|
||||
*
|
||||
* @param dst pointer to destination message object
|
||||
* @param src pointer to source message object
|
||||
*
|
||||
* @sa msg_addrinfo(), msg_get_address(), msg_set_address(), msg_addr_zero().
|
||||
*/
|
||||
void msg_addr_copy(msg_t *dst, msg_t const *src)
|
||||
{
|
||||
dst->m_addrinfo = src->m_addrinfo;
|
||||
dst->m_addrinfo.ai_next = NULL;
|
||||
dst->m_addrinfo.ai_canonname = NULL;
|
||||
memcpy(dst->m_addrinfo.ai_addr = &dst->m_addr->su_sa,
|
||||
src->m_addr, src->m_addrinfo.ai_addrlen);
|
||||
if (dst->m_addrinfo.ai_addrlen < sizeof(dst->m_addr))
|
||||
memset((char *)dst->m_addr + dst->m_addrinfo.ai_addrlen, 0,
|
||||
sizeof(dst->m_addr) - dst->m_addrinfo.ai_addrlen);
|
||||
}
|
||||
|
||||
|
||||
/** Get error classification flags.
|
||||
*
|
||||
* @relatesalso msg_s
|
||||
*
|
||||
* If the message parser fails to parse certain headers in the message, it
|
||||
* sets the corresponding extract error flags. The flags corresponding to
|
||||
* each header are stored in the message parser (msg_mclass_t) structure.
|
||||
* They are set when the header is added to the parser table.
|
||||
*
|
||||
* The SIP flags are defined in <sofia-sip/sip_headers.h>. For well-known
|
||||
* SIP headers, the flags for each header are listed in a separate text file
|
||||
* (sip_bad_mask) read by msg_parser.awk.
|
||||
*
|
||||
* The flags can be used directly by NTA (the mask triggering 400 response
|
||||
* is set with NTATAG_BAD_REQ_MASK(), the mask triggering response messages
|
||||
* to be dropped is set with NTATAG_BAD_RESP_MASK()). Alternatively the
|
||||
* application can check them based on the method or required SIP features.
|
||||
*
|
||||
* @sa msg_mclass_insert_with_mask(), NTATAG_BAD_REQ_MASK(),
|
||||
* NTATAG_BAD_RESP_MASK().
|
||||
*/
|
||||
unsigned msg_extract_errors(msg_t const *msg)
|
||||
{
|
||||
return msg ? msg->m_extract_err : (unsigned)-1;
|
||||
}
|
||||
|
||||
|
||||
/** Get error number associated with message.
|
||||
*
|
||||
* @relatesalso msg_s
|
||||
*
|
||||
* @param msg pointer to msg object
|
||||
*
|
||||
*/
|
||||
int msg_errno(msg_t const *msg)
|
||||
{
|
||||
return msg ? msg->m_errno : EINVAL;
|
||||
}
|
||||
|
||||
/** Set error number associated with message.
|
||||
*
|
||||
* @relatesalso msg_s
|
||||
*
|
||||
* @param msg pointer to msg object
|
||||
* @param err error value (as defined in <sofia-sip/su_errno.h>).
|
||||
*
|
||||
*/
|
||||
void msg_set_errno(msg_t *msg, int err)
|
||||
{
|
||||
if (msg)
|
||||
msg->m_errno = err;
|
||||
}
|
||||
@@ -0,0 +1,506 @@
|
||||
/* -*- text -*- */
|
||||
|
||||
/**@MODULEPAGE "msg" - Message Parser Module
|
||||
|
||||
@section msg_meta Module Meta Information
|
||||
|
||||
This module contains parser and functions for manipulating messages and
|
||||
headers for text-based protocols like SIP, HTTP or RTSP. It also
|
||||
provides parsing of MIME headers and MIME multipart messages common to
|
||||
these protocols.
|
||||
|
||||
@CONTACT Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
|
||||
@STATUS @SofiaSIP Core library
|
||||
|
||||
@LICENSE LGPL
|
||||
|
||||
@par Contributor(s):
|
||||
- Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
|
||||
@section msg_contents Contents of msg Module
|
||||
|
||||
The msg module contains the public header files as follows:
|
||||
- <sofia-sip/msg.h> base message interfaces
|
||||
- <sofia-sip/msg_types.h> message and header struct definitions and typedefs
|
||||
- <sofia-sip/msg_protos.h> prototypes of header-specific functions for generic headers
|
||||
- <sofia-sip/msg_header.h> function prototypes and macros for manipulating message
|
||||
headers
|
||||
- <sofia-sip/msg_addr.h> functions for accessing network addresses and I/O vectors
|
||||
associated with the message
|
||||
- <sofia-sip/msg_date.h> types and functions for handling dates and times
|
||||
- <sofia-sip/msg_mime.h> types, function prototypes and macros for MIME headers
|
||||
and @ref msg_multipart "multipart messages"
|
||||
- <sofia-sip/msg_mime_protos.h> prototypes of MIME-header-specific functions
|
||||
|
||||
In addition to this interface, the @ref msg_parser "parser documentation"
|
||||
contains description of the functionality required when an existing parser
|
||||
is extended by a new header or a parser is created for a completely new
|
||||
protocol. It is possible to add new headers to the parser or extend the
|
||||
definition of existing ones. The header files used for constructing these
|
||||
parsers are as follows:
|
||||
- <sofia-sip/msg_parser.h> parsing functions, macros
|
||||
- <sofia-sip/msg_mclass.h> message factory object definition
|
||||
- <sofia-sip/msg_mclass_hash.h> hashing of header names
|
||||
|
||||
@section msg_overview Parsers, Messages and Headers
|
||||
|
||||
The Sofia @b msg module contains interface to the text-based parsers for
|
||||
RFC822-like message, the header and message objects. Currently, there
|
||||
are three parsers defined: SIP, HTTP, and MIME.
|
||||
|
||||
The C structure corresponding to each header is defined either in a
|
||||
<sofia-sip/msg_types.h> or in a protocol-specific header file. These
|
||||
protocol-specific header files include <sofia-sip/sip.h>, <sofia-sip/http.h>, and
|
||||
<sofia-sip/msg_mime.h>. For each header, there is defined a @em header @em class
|
||||
structure, some standard functions, and tags for including them in tag
|
||||
lists.
|
||||
|
||||
As a convention, all the identifiers for SIP headers start with prefix @c
|
||||
sip and all the macros with @c SIP. Same thing holds for HTTP, too: it
|
||||
uses prefix @c http. However, the MIME headers
|
||||
and the functions related to them are defined within the @b msg module and
|
||||
they use prefix @c msg. If a SIP or HTTP header uses a structure
|
||||
defined in <sofia-sip/msg_types.h>, there is a typedef suitable for the particular
|
||||
protocol, for example @b Accept header is defined multiple times:
|
||||
|
||||
@code
|
||||
typedef struct msg_accept_s sip_accept_t;
|
||||
typedef struct msg_accept_s http_accept_t;
|
||||
@endcode
|
||||
|
||||
For header @e X of protocol @e NS, there are types, functions, macros and
|
||||
header class as follows:
|
||||
|
||||
- @c ns_X_t is the structure used to store parsed header,
|
||||
- @c ns_hclass_t @c ns_X_class[] contains the @em header @em class
|
||||
for header X,
|
||||
- @c NS_X_INIT() initializes a static instance of @c ns_X_t,
|
||||
- @c ns_X_init() initializes a dynamic instance of @c ns_X_t,
|
||||
- @c ns_is_X() tests if header object is instance of header X,
|
||||
- @c ns_X_make() creates a header X object by decoding given string,
|
||||
- @c ns_X_format() creates a header X object by decoding given
|
||||
@c printf() list,
|
||||
- @c ns_X_dup() duplicates (deeply copies) the header X,
|
||||
- @c ns_X_copy() copies the header X,
|
||||
- @c NSTAG_X() is used include instance of @c ns_X_t in a tag list, and
|
||||
- @c NSTAG_X_STR() is used to include string containing value header
|
||||
in a tag list.
|
||||
|
||||
The declarations of header tags and the prototypes for these functions can
|
||||
be imported separately from the type definitions, for instance, the tags
|
||||
related to SIP headers are declared in the include file
|
||||
<sofia-sip/sip_tag.h>, and the header-specific functions in
|
||||
<sofia-sip/sip_header.h>.
|
||||
|
||||
@section parser_intro Parsing Text Messages
|
||||
|
||||
Sofia text parser follows @em recursive-descent principle. In other words,
|
||||
it is a program that descends the syntax tree top-down recursively.
|
||||
(All syntax trees have root at top and they grow downwards.)
|
||||
|
||||
In the case of SIP, HTTP and other similar protocols, such a parser is very
|
||||
efficient. The parser can choose between different forms based on each
|
||||
token, as the protocol syntax is carefully designed so that it requires only
|
||||
minimal scan-ahead. It is also easy to extend a recursive-descent parser via
|
||||
a standard API, unlike, for instance, a LALR parser generated by @em Bison.
|
||||
|
||||
The abstract message module @b msg contains a high-level parser engine that
|
||||
drives the parsing process and invokes the protocol-specific parser for each
|
||||
header. As there is no low-layer framing between the RFC822-style messages,
|
||||
the parser considers any received data, be it a UDP datagram or a TCP
|
||||
stream, as a @em byte @em stream. The protocol-specific parsers controls how
|
||||
a byte stream is split into separate messages or if it consists of a single
|
||||
message only.
|
||||
|
||||
The parser engine works by separating stream into fragments, then passing
|
||||
the fragment to a suitable parser. A fragment is a piece of message that is
|
||||
parsed during a single step: the first line, each header, the empty line
|
||||
between headers and message body, the message body. (In case of HTTP, the
|
||||
message body can consists of multiple fragments known as chunks.)
|
||||
|
||||
The parser starts by separating the first line (e.g., request or status
|
||||
line) from the byte stream, then passing the line to the suitable parser.
|
||||
After first line comes the message headers. The parser continues parsing
|
||||
process by extracting headers, each on their own line, from the stream and
|
||||
passing contents of each header to its parser. The message structure is
|
||||
populated based on the parsing results. When an empty line - indicating end
|
||||
of headers - is encountered, the control is passed to the protocol-specific
|
||||
parser. Protocol-specific functions take care of extracting the possible
|
||||
message body from the byte stream.
|
||||
|
||||
After parsing process is completed, it can be given to the upper layers
|
||||
(typically a protocol state machine). The parser continues processing the
|
||||
stream and feeding the messages to protocol engine until the end of the
|
||||
stream is reached.
|
||||
|
||||
@image html sip-parser.gif Separating byte stream to messages
|
||||
@image latex sip-parser.eps Separating byte stream to messages
|
||||
|
||||
When the parsing process has completed, the first line, each header,
|
||||
separator and the message body are all in their own fragment structure. The
|
||||
fragments form a dual-linked list known as @e fragment @e chain as shown in
|
||||
the above figure. The memory buffers for the message, the fragment chain,
|
||||
and a whole lot of other stuff is held by the generic message type, #msg_t,
|
||||
defined in <msg.h>. The internal structure of #msg_t is known only within @b
|
||||
msg module and it is opaque to other modules.
|
||||
|
||||
The @b msg parser engine also drives the reverse process, invoking the
|
||||
encoding method of each fragment so that the whole outgoing message can be
|
||||
encoded properly.
|
||||
|
||||
@section msg_header_struct Message Header as a C struct
|
||||
|
||||
Just separating headers from each other and from the message body is not
|
||||
usually enough. When a header contains structured data, the header contents
|
||||
should be converted to a form that is convenient to use from C programs. For
|
||||
that purpose, the message parser needs a parsing function specific to each
|
||||
individual header. This parsing function divides the contents of the header
|
||||
into semantically meaningful segments and stores the result in the structure
|
||||
specific to each header.
|
||||
|
||||
The parser engine passes the fragment contents to the parsing function after
|
||||
it has separated the fragment from the rest of the message. The parser
|
||||
engine selects correct @e header @e class either by implication (in case of
|
||||
first line), or it searches for the header class from the hash table using
|
||||
the header name as the hash key. The @e header @e class contains a pointer
|
||||
to the parsing function. The parser has also special header classes for
|
||||
headers with errors and @e unknown headers, header with a name that is not
|
||||
regocnized by the parser.
|
||||
|
||||
For instance, the Accept header has following syntax:
|
||||
@code
|
||||
Accept = "Accept" ":" #( media-range [ accept-params ] )
|
||||
|
||||
media-range = ( "*" "/" "*"
|
||||
| ( type "/" "*" )
|
||||
| ( type "/" subtype ) ) *( ";" parameter )
|
||||
|
||||
accept-params = ";" "q" "=" qvalue *( accept-extension )
|
||||
|
||||
accept-extension = ";" token [ "=" ( token | quoted-string ) ]
|
||||
@endcode
|
||||
|
||||
When an Accept header is parsed, the header parser function (msg_accept_d())
|
||||
separates the @e type, @e subtype, and each parameter in the list to
|
||||
strings. The parsing result is assigned to a #msg_accept_t structure, which is
|
||||
defined as follows:
|
||||
|
||||
@code
|
||||
typedef struct msg_accept_s
|
||||
{
|
||||
msg_common_t ac_common[1]; //< Common fragment info
|
||||
msg_accept_t *ac_next; //< Pointer to next Accept header
|
||||
char const *ac_type; //< Pointer to type/subtype
|
||||
char const *ac_subtype; //< Points after first slash in type
|
||||
msg_param_t const *ac_params; //< List of parameters
|
||||
msg_param_t ac_q; //< Value of q parameter
|
||||
}
|
||||
msg_accept_t;
|
||||
@endcode
|
||||
|
||||
The string containing the @e type is put into the @c ac_type field, the @e
|
||||
subtype after slash in the can be found in the @c ac_subtype field, and the
|
||||
list of @e accept-params (together with media-specific-parameters) is put in
|
||||
the @c ac_params array. If there is a @e q parameter present, a pointer to
|
||||
the @c qvalue is assigned to @c ac_q field.
|
||||
|
||||
In the beginning of the header structure there are two boilerplate members.
|
||||
The @c ac_common[1] contains information common to all message fragments.
|
||||
The @c ac_next is a pointer to next header field with the same name, in case
|
||||
a message contains multiple @b Accept headers or multiple comma-separated
|
||||
header fields are located in a single line.
|
||||
|
||||
@section msg_object_example Representing a Message as a C struct
|
||||
|
||||
It is not enough to represent a message as a list of headers following each
|
||||
other. The programmer also needs a convenient way to access certain headers
|
||||
at the message level, for example, accessing directly the @b Accept header
|
||||
instead of going through all headers and examining their name. The
|
||||
structured view to the message is provided via a message-specific C struct.
|
||||
In general, its type is msg_pub_t (it provides public view to message). The
|
||||
protocol-specific type is #sip_t, #http_t or #msg_multipart_t for
|
||||
SIP, HTTP and MIME, respectively.
|
||||
|
||||
So, a single message is represented by two objects, first object (#msg_t) is
|
||||
private to the @b msg module and opaque by an application programmer, second
|
||||
(#sip_t, #http_t or #msg_multipart_t) is a public protocol-specific
|
||||
structure accessible by all.
|
||||
|
||||
@note The application programmer can obtain a pointer to the
|
||||
protocol-specific structure from an #msg_t object using msg_public()
|
||||
function. The msg_public() takes a protocol tag, a well-known identifier, as
|
||||
its argument. The SIP, HTTP and MIME already define a wrapper around
|
||||
msg_public(), for example, a #sip_t structure can be obtained with
|
||||
sip_object() function (or macro).
|
||||
|
||||
As an example, the #sip_t structure is defined as follows:
|
||||
@code
|
||||
typedef struct sip_s {
|
||||
msg_common_t sip_common[1]; // Used with recursive inclusion
|
||||
msg_pub_t *sip_next; // Ditto
|
||||
void *sip_user; // Application data
|
||||
unsigned sip_size; // Size of the structure with
|
||||
// extension headers
|
||||
int sip_flags; // Parser flags
|
||||
|
||||
sip_error_t *sip_error; // Erroneous headers
|
||||
|
||||
sip_request_t *sip_request; // Request line
|
||||
sip_status_t *sip_status; // Status line
|
||||
|
||||
sip_via_t *sip_via; // Via (v)
|
||||
sip_route_t *sip_route; // Route
|
||||
sip_record_route_t *sip_record_route; // Record-Route
|
||||
sip_max_forwards_t *sip_max_forwards; // Max-Forwards
|
||||
...
|
||||
} sip_t;
|
||||
@endcode
|
||||
|
||||
As you can see above, the public #sip_t structure contains the common
|
||||
header members that are also found in the beginning of a header
|
||||
structure. The @e sip_size indicates the size of the structure - the
|
||||
application can extend the parser and #sip_t structure beyond the
|
||||
original size. The @e sip_flags contains various flags used during the
|
||||
parsing and printing process. They are documented in the <msg.h>. These
|
||||
boilerplate members are followed by the pointers to various message
|
||||
elements and headers.
|
||||
|
||||
@section msg_parsing_example Result of Parsing Process
|
||||
|
||||
Let us now show how a simple message is parsed and presented to the
|
||||
applications. As an exampe, we choose a SIP request message with method BYE,
|
||||
including only the mandatory fields:
|
||||
@code
|
||||
BYE sip:joe@example.com SIP/2.0
|
||||
Via: SIP/2.0/UDP sip.example.edu;branch=d7f2e89c.74a72681
|
||||
Via: SIP/2.0/UDP pc104.example.edu:1030;maddr=110.213.33.19
|
||||
From: Bobby Brown <sip:bb@example.edu>;tag=77241a86
|
||||
To: Joe User <sip:joe@example.com>;tag=7c6276c1
|
||||
Call-ID: 4c4e911b@pc104.example.edu
|
||||
CSeq: 2
|
||||
@endcode
|
||||
|
||||
The figure below shows the layout of the BYE message above after parsing:
|
||||
|
||||
@image html sip-parser2.gif BYE message and its representation in C
|
||||
@image latex sip-parser2.eps BYE message and its representation in C
|
||||
|
||||
The leftmost box represents the message of type #msg_t. Next box from
|
||||
the left reprents the #sip_t structure, which contains pointers to a
|
||||
header objects. The next column contains the header objects. There is
|
||||
one header object for each message fragment. The rightmost box represents
|
||||
the I/O buffer used when the message was received. Note that the I/O
|
||||
buffer may be non-continous and composed of many separate memory areas.
|
||||
|
||||
The message object has link to the public message structure (@a
|
||||
m_object), to the dual-linked fragment chain (@a m_frags) and to the I/O
|
||||
buffer (@a m_buffer). The public message structure contains pointers to
|
||||
the headers according to their type. If there are multiple headers of
|
||||
the same type (like there are two Via headers in the above message), the
|
||||
headers are put into a single-linked list.
|
||||
|
||||
Each fragment has pointers to successing and preceding fragment. It also
|
||||
contains pointer to the corresponding data within the I/O buffer and its
|
||||
length.
|
||||
|
||||
The main purpose of the fragment chain is to preserve the original order
|
||||
of the headers. If there were an third Via header after CSeq in the
|
||||
message, the fragment representing it would be after the CSeq header in
|
||||
the fragment chain but after second Via in the header list.
|
||||
|
||||
@section msg_parsing_memory Example: Parsing a Complete Message
|
||||
|
||||
The following code fragment is an example of parsing a complete message. The
|
||||
parsing process is more hairy when there is stream to be parsed.
|
||||
|
||||
@code
|
||||
msg_t *parse_memory(msg_mclass_t const *mclass, char const data[], int len)
|
||||
{
|
||||
msg_t *msg;
|
||||
int m;
|
||||
msg_iovec_t iovec[2] = {{ 0 }};
|
||||
|
||||
msg = msg_create(mclass, 0);
|
||||
if (!msg)
|
||||
return NULL;
|
||||
|
||||
m = msg_recv_iovec(msg, iovec, 2, n, 1);
|
||||
if (m < 0) {
|
||||
msg_destroy(msg);
|
||||
return NULL;
|
||||
}
|
||||
assert(m <= 2);
|
||||
assert(iovec[0].mv_len + iovec[1].mv_len == n);
|
||||
|
||||
memcpy(iovec[0].mv_base, data, n = iovec[0].mv_len);
|
||||
if (m == 2)
|
||||
memcpy(iovec[1].mv_base + n, data + n, iovec[1].mv_len);
|
||||
|
||||
msg_recv_commit(msg, iovec[0].mv_len + iovec[1].mv_len, 1);
|
||||
|
||||
m = msg_extract(msg);
|
||||
assert(m != 0);
|
||||
if (m < 0) {
|
||||
msg_destroy(msg);
|
||||
return NULL;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
@endcode
|
||||
|
||||
Let's go through this simple function, step by step. First, we get the @a
|
||||
data pointer and its size in bytes, @a len. We first initialize an I/O
|
||||
vector used to represent message with the parser.
|
||||
|
||||
@code
|
||||
msg_t *parse_memory(msg_mclass_t const *mclass, char const data[], int len)
|
||||
{
|
||||
msg_t *msg;
|
||||
int m;
|
||||
msg_iovec_t iovec[2] = {{ 0 }};
|
||||
@endcode
|
||||
|
||||
The message class @a mclass (a parser driver object, #msg_mclass_t) is used
|
||||
to represent a particular protocol-specific parser instance. When a message
|
||||
object is created, it is given as an argument to msg_create() function:
|
||||
|
||||
@code
|
||||
msg = msg_create(mclass, 0);
|
||||
if (!msg)
|
||||
return NULL;
|
||||
@endcode
|
||||
|
||||
Next we obtain a memory buffer for data with msg_recv_iovec(). The memory
|
||||
buffer is usually a single continous memory area, but in some cases it may
|
||||
consist of two distinct areas. Therefore the @a iovec is used here to pass
|
||||
the buffers around. The @a iovec is also very handly as it can be directly
|
||||
passed to various system I/O calls.
|
||||
|
||||
@code
|
||||
m = msg_recv_iovec(msg, iovec, 2, n, 1);
|
||||
if (m < 0) {
|
||||
msg_destroy(msg);
|
||||
return NULL;
|
||||
}
|
||||
@endcode
|
||||
|
||||
These assumptions hold always true when you call msg_recv_iovec() first
|
||||
time with a complete message:
|
||||
|
||||
@code
|
||||
assert(m >= 1 && m <= 2);
|
||||
assert(iovec[0].mv_len + iovec[1].mv_len == n);
|
||||
@endcode
|
||||
|
||||
Next, we copy the data to the I/O vector and commit the copied data to the
|
||||
message. Earlier with msg_recv_iovec() we allocated buffer space for data,
|
||||
now calling msg_recv_commit() indicates that valid data has been copied to
|
||||
the buffer. The last parameter to msg_recv_commit() indicates that the end
|
||||
of stream is encountered and no more data is to be expected.
|
||||
|
||||
@code
|
||||
memcpy(iovec[0].mv_base, data, n = iovec[0].mv_len);
|
||||
if (m == 2)
|
||||
memcpy(iovec[1].mv_base + n, data + n, iovec[1].mv_len);
|
||||
|
||||
msg_recv_commit(msg, iovec[0].mv_len + iovec[1].mv_len, 1);
|
||||
@endcode
|
||||
|
||||
We call msg_extract() next; it takes care of parsing the message. A fatal
|
||||
parsing error is indicated by returning -1. If the message is incomplete,
|
||||
msg_extract() returns 0. When a complete message has been parsed, a positive
|
||||
value is returned. We know that a message cannot be incomplete, as a call to
|
||||
msg_recv_commit() indicated to the parser that the end-of-stream has been
|
||||
encountered.
|
||||
|
||||
@code
|
||||
m = msg_extract(msg);
|
||||
assert(m != 0);
|
||||
if (m < 0) {
|
||||
msg_destroy(msg);
|
||||
return NULL;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
@endcode
|
||||
|
||||
*/
|
||||
|
||||
/**@class msg_s msg.h
|
||||
*
|
||||
* @brief Message object.
|
||||
*
|
||||
* The message object is used by Sofia parsers for SIP and HTTP
|
||||
* protocols. The message object has an abstract, protocol-independent
|
||||
* inteface type #msg_t, and a separate public protocol-specific interface
|
||||
* #msg_pub_t (which is typedef'ed to #sip_t or #http_t depending
|
||||
* on the protocol).
|
||||
*
|
||||
* The main interface to abstract messages is defined in <sofia-sip/msg.h>. The
|
||||
* network I/O interface used by transport protocols is defined in
|
||||
* <sofia-sip/msg_addr.h>. The protocol-specific parser table, also known as message
|
||||
* class, is defined in <sofia-sip/msg_mclass.h>. (The message class is used as a
|
||||
* factory object when a message object is created with msg_create()).
|
||||
*/
|
||||
|
||||
/**@typedef typedef struct msg_s msg_t;
|
||||
*
|
||||
* Message object.
|
||||
*
|
||||
* The @a msg_t is the type of a message object used by Sofia signaling
|
||||
* protocols and parsers. Its contents are not directly accessible.
|
||||
*/
|
||||
|
||||
/**@typedef typedef struct msg_common_s msg_common_t;
|
||||
*
|
||||
* Common part of header.
|
||||
*
|
||||
* The @a msg_common_t is the base type of a message headers used by
|
||||
* protocol parsers. Instead of #msg_common_t, most interfaces use
|
||||
* #msg_header_t, which is supposed to be a union of all possible headers.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup msg_parser Parser Building Blocks
|
||||
*
|
||||
* This submodule contains the functions and types for building a
|
||||
* protocol-specific parser.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup msg_headers Headers
|
||||
*
|
||||
* This submodule contains the functions and types for handling message
|
||||
* headers and other elements.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup msg_mime MIME Headers
|
||||
*
|
||||
* This submodule contains the header classes, functions and types for
|
||||
* handling MIME headers (@RFC2045) and MIME multipart (@RFC2046) processing.
|
||||
*
|
||||
* The MIME headers implemented are as follows:
|
||||
* - @ref msg_accept "@b Accept header"
|
||||
* - @ref msg_accept_charset "@b Accept-Charser header"
|
||||
* - @ref msg_accept_encoding "@b Accept-Encoding header"
|
||||
* - @ref msg_accept_language "@b Accept-Language header"
|
||||
* - @ref msg_content_disposition "@b Content-Disposition header"
|
||||
* - @ref msg_content_encoding "@b Content-Encoding header"
|
||||
* - @ref msg_content_id "@b Content-ID header"
|
||||
* - @ref msg_content_location "@b Content-Location header"
|
||||
* - @ref msg_content_language "@b Content-Language header"
|
||||
* - @ref msg_content_md5 "@b Content-MD5 header"
|
||||
* - @ref msg_content_transfer_encoding "@b Content-Transfer-Encoding header"
|
||||
* - @ref msg_mime_version "@b MIME-Version header"
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup test_msg Testing Parser
|
||||
*
|
||||
* This submodule contains the functions and types for building a
|
||||
* parser objects for testing purposes.
|
||||
*/
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 msg_parser
|
||||
* @CFILE msg_auth.c
|
||||
*
|
||||
* Functions for handling authentication-related headers
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Tue Jun 13 02:57:51 2000 ppessi
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sofia-sip/msg.h>
|
||||
#include <sofia-sip/msg_parser.h>
|
||||
#include <sofia-sip/msg_header.h>
|
||||
#include <sofia-sip/bnf.h>
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Scan and compact an authentication parameter.
|
||||
*
|
||||
* Scan an authentication parameter, which has syntax as follows:
|
||||
* @code
|
||||
* auth-item = auth-param | base64-string
|
||||
* auth-param = token [ "=" (token | quoted-string)]
|
||||
* @endcode
|
||||
*
|
||||
* Parameters:
|
||||
* @param s pointer to string to scan
|
||||
*
|
||||
* @return Number of characters scanned, or zero upon an error.
|
||||
*/
|
||||
static size_t msg_auth_item_scan(char *start)
|
||||
{
|
||||
char *p, *s;
|
||||
|
||||
p = s = start;
|
||||
|
||||
/* XXX */
|
||||
|
||||
return start - s;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ====================================================================== */
|
||||
/*
|
||||
* auth = ("Authorization" | "Encryption" |
|
||||
* "Proxy-Authenticate" | "Proxy-Authorization" |
|
||||
* "Response-Key" | "WWW-Authenticate") ":"
|
||||
* scheme 1*SP #auth-param
|
||||
* scheme = token
|
||||
* auth-param = token | token "=" token | token "=" quoted-string
|
||||
*/
|
||||
|
||||
/** Parse security headers. */
|
||||
issize_t msg_auth_d(su_home_t *home,
|
||||
msg_header_t *h,
|
||||
char *s,
|
||||
isize_t slen)
|
||||
{
|
||||
msg_auth_t *au = (msg_auth_t *)h;
|
||||
|
||||
au->au_scheme = s;
|
||||
|
||||
skip_token(&s);
|
||||
if (!IS_LWS(*s)) return -1;
|
||||
*s++ = '\0'; /* NUL-terminate scheme */
|
||||
|
||||
return msg_commalist_d(home, &s, (msg_param_t **)&au->au_params,
|
||||
NULL /* msg_auth_item_scan */);
|
||||
}
|
||||
|
||||
issize_t msg_auth_e(char b[], isize_t bsiz, msg_header_t const *h, int f)
|
||||
{
|
||||
msg_auth_t const *au = (msg_auth_t *)h;
|
||||
int compact = MSG_IS_COMPACT(f);
|
||||
char *b0 = b, *end = b + bsiz;
|
||||
|
||||
MSG_STRING_E(b, end, au->au_scheme);
|
||||
if (au->au_params) {
|
||||
MSG_CHAR_E(b, end, ' ');
|
||||
MSG_COMMALIST_E(b, end, au->au_params, compact);
|
||||
}
|
||||
MSG_TERM_E(b, end);
|
||||
|
||||
return b - b0;
|
||||
}
|
||||
|
||||
/**@internal
|
||||
* 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.
|
||||
*/
|
||||
isize_t msg_auth_dup_xtra(msg_header_t const *h, isize_t offset)
|
||||
{
|
||||
msg_auth_t const *au = h->sh_auth;
|
||||
|
||||
MSG_PARAMS_SIZE(offset, au->au_params);
|
||||
offset += MSG_STRING_SIZE(au->au_scheme);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**Duplicate one msg_auth_t object. */
|
||||
char *msg_auth_dup_one(msg_header_t *dst,
|
||||
msg_header_t const *src,
|
||||
char *b,
|
||||
isize_t xtra)
|
||||
{
|
||||
msg_auth_t *au = dst->sh_auth;
|
||||
msg_auth_t const *o = src->sh_auth;
|
||||
char *end = b + xtra;
|
||||
|
||||
b = msg_params_dup(&au->au_params, o->au_params, b, xtra);
|
||||
MSG_STRING_DUP(b, au->au_scheme, o->au_scheme);
|
||||
|
||||
assert(b <= end); (void)end;
|
||||
|
||||
return b;
|
||||
}
|
||||
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 msg_headers
|
||||
* @CFILE msg_basic.c
|
||||
* @brief Basic header handling.
|
||||
*
|
||||
* This file contains implementation of basic headers, that is, generic
|
||||
* headers like Subject or Organization containing non-structured text only,
|
||||
* numeric headers like Content-Length or Max-Forwards containing only an
|
||||
* 32-bit unsigned integer, or token list headers like Supported or Allow.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Fri Feb 23 19:51:55 2001 ppessi
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sofia-sip/su_alloc.h>
|
||||
|
||||
#include <sofia-sip/msg.h>
|
||||
#include <sofia-sip/bnf.h>
|
||||
#include <sofia-sip/msg_parser.h>
|
||||
#include <sofia-sip/msg_header.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define msg_generic_update NULL
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
/**@ingroup msg_headers
|
||||
* @defgroup msg_error Erroneous Headers
|
||||
*
|
||||
* The erroneous headers are stored in #msg_error_t structure.
|
||||
*
|
||||
* @note Parser may put other headers (like duplicate Content-Length
|
||||
* headers) into the list of erroneous headers. If the list of erroneous
|
||||
* headers is processed, the header type must be validated first by calling
|
||||
* msg_is_error() (or by other relevant tests).
|
||||
*/
|
||||
|
||||
/**@ingroup msg_error
|
||||
* @typedef typedef struct msg_error_s msg_error_t;
|
||||
* Type for erroneous headers.
|
||||
*/
|
||||
|
||||
isize_t msg_error_dup_xtra(msg_header_t const *h, isize_t offset);
|
||||
char *msg_error_dup_one(msg_header_t *dst, msg_header_t const *src,
|
||||
char *b, isize_t xtra);
|
||||
|
||||
msg_hclass_t msg_error_class[] =
|
||||
MSG_HEADER_CLASS(msg_, error, "", "", er_common, append,
|
||||
msg_error, msg_generic);
|
||||
|
||||
issize_t msg_error_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
issize_t msg_error_e(char b[], isize_t bsiz, msg_header_t const *h, int flags)
|
||||
{
|
||||
/* There is no way to encode an erroneous header */
|
||||
return 0;
|
||||
}
|
||||
|
||||
isize_t msg_error_dup_xtra(msg_header_t const *h, isize_t offset)
|
||||
{
|
||||
return msg_default_dup_xtra(h, offset);
|
||||
}
|
||||
|
||||
char *msg_error_dup_one(msg_header_t *dst, msg_header_t const *src,
|
||||
char *b, isize_t xtra)
|
||||
{
|
||||
return msg_default_dup_one(dst, src, b, xtra);
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
/**@ingroup msg_headers
|
||||
* @defgroup msg_unknown Unknown Headers
|
||||
*
|
||||
* The unknown headers are handled with #msg_unknown_t structure. The whole
|
||||
* unknown header including its name is included in the header value string
|
||||
* @a g_value.
|
||||
*
|
||||
* @note It is possible to speed up parsing process by creating a parser
|
||||
* which does understand only a minimum number of headers. If such a parser
|
||||
* is used, some well-known headers are not regocnized or parser, but they
|
||||
* are treated as unknown and put unparsed into the list of unknown headers.
|
||||
*/
|
||||
|
||||
/**@ingroup msg_unknown
|
||||
* @typedef typedef struct msg_unknown_s msg_unknown_t;
|
||||
*
|
||||
* Type for unknown headers.
|
||||
*/
|
||||
|
||||
msg_hclass_t msg_unknown_class[] =
|
||||
MSG_HEADER_CLASS(msg_, unknown, "", "", un_common, append,
|
||||
msg_unknown, msg_generic);
|
||||
|
||||
issize_t msg_unknown_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen)
|
||||
{
|
||||
msg_unknown_t *un = (msg_unknown_t *)h;
|
||||
|
||||
if (msg_token_d(&s, &un->un_name) < 0 ||
|
||||
*s != ':')
|
||||
return -1;
|
||||
|
||||
*s++ = '\0';
|
||||
skip_lws(&s);
|
||||
un->un_value = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
issize_t msg_unknown_e(char b[], isize_t bsiz, msg_header_t const *h, int flags)
|
||||
{
|
||||
char *b0 = b, *end = b + bsiz;
|
||||
msg_unknown_t *un = (msg_unknown_t *)h;
|
||||
int const compact = MSG_IS_COMPACT(flags);
|
||||
|
||||
MSG_STRING_E(b, end, un->un_name);
|
||||
MSG_CHAR_E(b, end, ':');
|
||||
if (!compact) MSG_CHAR_E(b, end, ' ');
|
||||
MSG_STRING_E(b, end, un->un_value);
|
||||
|
||||
return b - b0;
|
||||
}
|
||||
|
||||
isize_t msg_unknown_dup_xtra(msg_header_t const *h, isize_t offset)
|
||||
{
|
||||
msg_unknown_t const *un = (msg_unknown_t *)h;
|
||||
return offset + MSG_STRING_SIZE(un->un_name) + MSG_STRING_SIZE(un->un_value);
|
||||
}
|
||||
|
||||
char *msg_unknown_dup_one(msg_header_t *dst, msg_header_t const *src,
|
||||
char *b, isize_t xtra)
|
||||
{
|
||||
msg_unknown_t *un = (msg_unknown_t *)dst;
|
||||
msg_unknown_t const *o = (msg_unknown_t *)src;
|
||||
char *end = b + xtra;
|
||||
|
||||
MSG_STRING_DUP(b, un->un_name, o->un_name);
|
||||
MSG_STRING_DUP(b, un->un_value, o->un_value);
|
||||
|
||||
assert(b <= end); (void)end;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
/**@ingroup msg_headers
|
||||
* @defgroup msg_payload Message Body
|
||||
*
|
||||
* The payload object contains the message body. The message body has no
|
||||
* structure, but it is stored in the @a pl_data buffer as a byte array.
|
||||
* Multiple payload objects may be linked to a list.
|
||||
*/
|
||||
|
||||
/**@ingroup msg_payload
|
||||
* @typedef typedef struct msg_payload_s msg_payload_t;
|
||||
*
|
||||
* The structure msg_payload_t contains representation of MIME message payload.
|
||||
*
|
||||
* The msg_payload_t is defined as follows:
|
||||
* @code
|
||||
* typedef struct msg_payload_s {
|
||||
* msg_common_t pl_common[1]; // Common fragment info
|
||||
* msg_header_t *pl_next; // Next payload object
|
||||
* char *pl_data; // Data - may contain zero bytes
|
||||
* usize_t pl_len; // Length of message payload
|
||||
* } msg_payload_t;
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
msg_hclass_t msg_payload_class[1] =
|
||||
MSG_HEADER_CLASS(msg_, payload, NULL, "", pl_common, append,
|
||||
msg_payload, msg_generic);
|
||||
|
||||
/** Create a MIME payload */
|
||||
msg_payload_t *msg_payload_create(su_home_t *home, void const *data, usize_t len)
|
||||
{
|
||||
msg_header_t *h = msg_header_alloc(home, msg_payload_class, len + 1);
|
||||
msg_payload_t *pl = h->sh_payload;
|
||||
|
||||
if (pl) {
|
||||
char *b = msg_header_data(h->sh_common);
|
||||
if (data)
|
||||
memcpy(b, data, len);
|
||||
else
|
||||
memset(b, 0, len);
|
||||
b[len] = 0;
|
||||
|
||||
h->sh_data = pl->pl_data = b;
|
||||
h->sh_len = pl->pl_len = len;
|
||||
|
||||
return pl;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Parse payload. */
|
||||
issize_t msg_payload_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen)
|
||||
{
|
||||
h->sh_payload->pl_len = slen;
|
||||
h->sh_payload->pl_data = s;
|
||||
|
||||
h->sh_len = slen;
|
||||
h->sh_data = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
issize_t msg_payload_e(char b[], isize_t bsiz, msg_header_t const *h, int flags)
|
||||
{
|
||||
size_t len = h->sh_payload->pl_len;
|
||||
|
||||
if (bsiz > 0) {
|
||||
memcpy(b, h->sh_payload->pl_data, bsiz > len ? len : bsiz);
|
||||
b[bsiz > len ? len : bsiz - 1] = '\0';
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
isize_t msg_payload_dup_xtra(msg_header_t const *h, isize_t offset)
|
||||
{
|
||||
return offset + h->sh_payload->pl_len + 1;
|
||||
}
|
||||
|
||||
char *msg_payload_dup_one(msg_header_t *dst,
|
||||
msg_header_t const *src,
|
||||
char *b,
|
||||
isize_t xtra)
|
||||
{
|
||||
msg_payload_t *pl = dst->sh_payload;
|
||||
msg_payload_t const *o = src->sh_payload;
|
||||
|
||||
memcpy(pl->pl_data = b, o->pl_data, pl->pl_len = o->pl_len);
|
||||
|
||||
pl->pl_common->h_data = pl->pl_data;
|
||||
pl->pl_common->h_len = pl->pl_len;
|
||||
|
||||
pl->pl_data[pl->pl_len] = 0; /* NUL terminate just in case */
|
||||
|
||||
return b + pl->pl_len + 1;
|
||||
}
|
||||
|
||||
usize_t msg_payload_length(msg_payload_t const *pl)
|
||||
{
|
||||
/* XXX */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
/**@ingroup msg_headers
|
||||
* @defgroup msg_separator Message Separator
|
||||
*
|
||||
* An empty line separates headers from the message body. In order to avoid
|
||||
* modifying messages with integrity protection, the separator line has its
|
||||
* own header structure which is included in the msg_t structure.
|
||||
*/
|
||||
|
||||
/**@ingroup msg_separator
|
||||
* @typedef typedef struct msg_separator_s msg_separator_t;
|
||||
*
|
||||
* The structure msg_separator_t contains representation of separator line
|
||||
* between message headers and body.
|
||||
*
|
||||
* The msg_separator_t is defined as follows:
|
||||
* @code
|
||||
* typedef struct msg_separator_s {
|
||||
* msg_common_t sep_common[1]; // Common fragment info
|
||||
* msg_header_t *sep_next; // Pointer to next header
|
||||
* char sep_data[4]; // NUL-terminated separator
|
||||
* } msg_separator_t;
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
msg_hclass_t msg_separator_class[] =
|
||||
MSG_HEADER_CLASS(msg_, separator, NULL, "", sep_common, single,
|
||||
msg_default, msg_generic);
|
||||
|
||||
/** Calculate length of line ending (0, 1 or 2). @internal */
|
||||
#define CRLF_TEST(s) ((s[0]) == '\r' ? ((s[1]) == '\n') + 1 : (s[0])=='\n')
|
||||
|
||||
/** Parse a separator line. */
|
||||
issize_t msg_separator_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen)
|
||||
{
|
||||
int len = CRLF_TEST(s);
|
||||
|
||||
if (len == 0 && slen > 0)
|
||||
return -1;
|
||||
|
||||
memcpy(h->sh_separator->sep_data, s, len);
|
||||
h->sh_separator->sep_data[len] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Encode a separator line. */
|
||||
issize_t msg_separator_e(char b[], isize_t bsiz, msg_header_t const *h, int flags)
|
||||
{
|
||||
size_t n = strlen(h->sh_separator->sep_data);
|
||||
|
||||
if (bsiz > n)
|
||||
strcpy(b, h->sh_separator->sep_data);
|
||||
|
||||
return (issize_t)n;
|
||||
}
|
||||
|
||||
msg_separator_t *msg_separator_create(su_home_t *home)
|
||||
{
|
||||
msg_separator_t *sep =
|
||||
msg_header_alloc(home, msg_separator_class, 0)->sh_separator;
|
||||
|
||||
if (sep)
|
||||
strcpy(sep->sep_data, CRLF);
|
||||
|
||||
return sep;
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
|
||||
@@ -0,0 +1,413 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 msg_parser
|
||||
* @CFILE msg_date.c
|
||||
* @brief Parser for HTTP-Date and HTTP-Delta.
|
||||
*
|
||||
* Parsing functions for @RFC1123 (GMT) date.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Wed Apr 11 18:57:06 2001 ppessi
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sofia-sip/msg_date.h>
|
||||
#include <sofia-sip/bnf.h>
|
||||
|
||||
#include <sofia-sip/su_time.h>
|
||||
|
||||
/** Return current time as seconds since Mon, 01 Jan 1900 00:00:00 GMT. */
|
||||
msg_time_t msg_now(void)
|
||||
{
|
||||
return su_now().tv_sec;
|
||||
}
|
||||
|
||||
#define is_digit(c) ((c) >= '0' && (c) <= '9')
|
||||
|
||||
/**Epoch year. @internal
|
||||
*
|
||||
* First day of the epoch year should be Monday.
|
||||
*/
|
||||
#define EPOCH 1900
|
||||
/** Is this year a leap year? @internal */
|
||||
#define LEAP_YEAR(y) ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
|
||||
/** Day number of New Year Day of given year. @internal */
|
||||
#define YEAR_DAYS(y) \
|
||||
(((y)-1) * 365 + ((y)-1) / 4 - ((y)-1) / 100 + ((y)-1) / 400)
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
static unsigned char const days_per_months[12] =
|
||||
{
|
||||
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
|
||||
};
|
||||
|
||||
/** Offset of first day of the month with formula day = 30 * month + offset. */
|
||||
static signed char const first_day_offset[12] =
|
||||
{
|
||||
0, 1, -1, 0, 0, 1, 1, 2, 3, 3, 4, 4
|
||||
};
|
||||
|
||||
static char const wkdays[7 * 4] =
|
||||
"Mon\0" "Tue\0" "Wed\0" "Thu\0" "Fri\0" "Sat\0" "Sun";
|
||||
|
||||
static char const months[12 * 4] =
|
||||
"Jan\0" "Feb\0" "Mar\0" "Apr\0" "May\0" "Jun\0"
|
||||
"Jul\0" "Aug\0" "Sep\0" "Oct\0" "Nov\0" "Dec";
|
||||
|
||||
/** Parse a month name.
|
||||
*
|
||||
* @return The function month_d() returns 0..11 if given first three letters
|
||||
* of month name, or -1 if no month name matches.
|
||||
*/
|
||||
static inline
|
||||
int month_d(char const *s)
|
||||
{
|
||||
unsigned const uc = ('a' - 'A') << 16 | ('a' - 'A') << 8 | ('a' - 'A');
|
||||
unsigned m;
|
||||
|
||||
if (!s[0] || !s[1] || !s[2])
|
||||
return -1;
|
||||
|
||||
#define MONTH_V(s) (uc | (((s[0]) << 16) + ((s[1]) << 8) + ((s[2]))))
|
||||
m = MONTH_V(s);
|
||||
|
||||
#define MONTH_D(n) \
|
||||
if (m == (uc | (months[4*(n)]<<16)|(months[4*(n)+1]<<8)|(months[4*(n)+2])))\
|
||||
return (n)
|
||||
|
||||
MONTH_D(0);
|
||||
MONTH_D(1);
|
||||
MONTH_D(2);
|
||||
MONTH_D(3);
|
||||
MONTH_D(4);
|
||||
MONTH_D(5);
|
||||
MONTH_D(6);
|
||||
MONTH_D(7);
|
||||
MONTH_D(8);
|
||||
MONTH_D(9);
|
||||
MONTH_D(10);
|
||||
MONTH_D(11);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Parse SP 2DIGIT ":" 2DIGIT ":" 2DIGIT SP */
|
||||
static inline
|
||||
int time_d(char const **ss,
|
||||
unsigned long *hour, unsigned long *min, unsigned long *sec)
|
||||
{
|
||||
char const *s = *ss;
|
||||
if (!IS_LWS(*s))
|
||||
return -1;
|
||||
skip_lws(&s);
|
||||
if (!is_digit(*s)) return -1;
|
||||
*hour = *s++ - '0'; if (is_digit(*s)) *hour = 10 * (*hour) + *s++ - '0';
|
||||
if (*s++ != ':' || !is_digit(s[0]) || !is_digit(s[1]))
|
||||
return -1;
|
||||
*min = 10 * s[0] + s[1] - 11 * '0'; s += 2;
|
||||
if (*s++ != ':' || !is_digit(s[0]) || !is_digit(s[1]))
|
||||
return -1;
|
||||
*sec = 10 * s[0] + s[1] - 11 * '0'; s += 2;
|
||||
if (*s) {
|
||||
if (!IS_LWS(*s)) return -1; skip_lws(&s);
|
||||
}
|
||||
*ss = s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Decode RFC1123-date, RFC822-date or asctime-date.
|
||||
*
|
||||
* The function msg_date_d() decodes <HTTP-date>, which may have
|
||||
* different formats.
|
||||
*
|
||||
* @code
|
||||
* HTTP-date = rfc1123-date / rfc850-date / asctime-date
|
||||
*
|
||||
* rfc1123-date = wkday "," SP date1 SP time SP "GMT"
|
||||
* date1 = 2DIGIT SP month SP 4DIGIT
|
||||
* ; day month year (e.g., 02 Jun 1982)
|
||||
*
|
||||
* rfc850-date = weekday "," SP date2 SP time SP "GMT"
|
||||
* date2 = 2DIGIT "-" month "-" 2DIGIT
|
||||
* ; day-month-year (e.g., 02-Jun-82)
|
||||
*
|
||||
* asctime-date = wkday SP date3 SP time SP 4DIGIT
|
||||
* date3 = month SP ( 2DIGIT / ( SP 1DIGIT ))
|
||||
* ; month day (e.g., Jun 2)
|
||||
*
|
||||
* time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
|
||||
* ; 00:00:00 - 23:59:59
|
||||
*
|
||||
* wkday = "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun"
|
||||
* weekday = "Monday" / "Tuesday" / "Wednesday"
|
||||
* / "Thursday" / "Friday" / "Saturday" / "Sunday"
|
||||
* month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun"
|
||||
* / "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
|
||||
* @endcode
|
||||
*/
|
||||
issize_t msg_date_d(char const **ss, msg_time_t *date)
|
||||
{
|
||||
char const *s = *ss;
|
||||
char const *wkday;
|
||||
char const *tz;
|
||||
unsigned long day, year, hour, min, sec;
|
||||
int mon;
|
||||
|
||||
if (!IS_TOKEN(*s) || !date)
|
||||
return -1;
|
||||
|
||||
wkday = s; skip_token(&s); if (*s == ',') s++;
|
||||
while (IS_LWS(*s)) s++;
|
||||
|
||||
if (is_digit(*s)) {
|
||||
day = *s++ - '0'; if (is_digit(*s)) day = 10 * day + *s++ - '0';
|
||||
|
||||
if (*s == ' ') {
|
||||
/* rfc1123-date =
|
||||
wkday "," SP 2DIGIT SP month SP 4DIGIT SP time SP "GMT"
|
||||
*/
|
||||
mon = month_d(++s); skip_token(&s);
|
||||
if (mon < 0 || !IS_LWS(*s)) return -1;
|
||||
s++;
|
||||
if (!is_digit(s[0]) || !is_digit(s[1]) ||
|
||||
!is_digit(s[2]) || !is_digit(s[3]))
|
||||
return -1;
|
||||
year = 1000 * s[0] + 100 * s[1] + 10 * s[2] + s[3] - 1111 * '0'; s += 4;
|
||||
}
|
||||
else if (*s == '-') {
|
||||
/* rfc822-date =
|
||||
weekday "," SP 2DIGIT "-" month "-" 2DIGIT SP time SP "GMT"
|
||||
*/
|
||||
|
||||
mon = month_d(++s);
|
||||
if (mon < 0 || s[3] != '-' ||
|
||||
!is_digit(s[4]) || !is_digit(s[5]))
|
||||
return -1;
|
||||
year = 10 * s[4] + s[5] - 11 * '0';
|
||||
if (is_digit(s[6]) && is_digit(s[7])) {
|
||||
/* rfc2822-date =
|
||||
weekday "," SP 2DIGIT "-" month "-" 4DIGIT SP time SP "GMT"
|
||||
*/
|
||||
year = year * 100 + 10 * s[6] + s[7] - 11 * '0';
|
||||
s += 8;
|
||||
}
|
||||
else {
|
||||
if (year >= 70)
|
||||
year = 1900 + year;
|
||||
else
|
||||
year = 2000 + year;
|
||||
s += 6;
|
||||
}
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
if (time_d(&s, &hour, &min, &sec) < 0) return -1;
|
||||
if (*s) {
|
||||
tz = s; skip_token(&s); skip_lws(&s);
|
||||
if (strncasecmp(tz, "GMT", 3) && strncasecmp(tz, "UCT", 3))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* actime-date =
|
||||
wkday SP month SP ( 2DIGIT | ( SP 1DIGIT )) SP time SP 4DIGIT */
|
||||
mon = month_d(s); skip_token(&s);
|
||||
if (mon < 0 || !IS_LWS(*s)) return -1; s++;
|
||||
while (IS_LWS(*s)) s++;
|
||||
if (!is_digit(*s)) return -1;
|
||||
day = *s++ - '0'; if (is_digit(*s)) day = 10 * day + *s++ - '0';
|
||||
if (time_d(&s, &hour, &min, &sec) < 0) return -1;
|
||||
/* Accept also unix date (if it is GMT) */
|
||||
if ((s[0] == 'G' && s[1] == 'M' && s[2] == 'T' && s[3] == ' ') ||
|
||||
(s[0] == 'U' && s[1] == 'T' && s[2] == 'C' && s[3] == ' '))
|
||||
s += 4;
|
||||
else if (s[0] == 'U' && s[1] == 'T' && s[2] == ' ')
|
||||
s += 3;
|
||||
if (!is_digit(s[0]) || !is_digit(s[1]) ||
|
||||
!is_digit(s[2]) || !is_digit(s[3]))
|
||||
return -1;
|
||||
year = 1000 * s[0] + 100 * s[1] + 10 * s[2] + s[3] - 1111 * '0'; s += 4;
|
||||
}
|
||||
|
||||
if (hour > 24 || min >= 60 || sec >= 60 ||
|
||||
(hour == 24 && min > 0 && sec > 0))
|
||||
return -1;
|
||||
|
||||
if (day == 0 || day > days_per_months[mon]) {
|
||||
if (day != 29 || mon != 1 || !LEAP_YEAR(year))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (year < EPOCH) {
|
||||
*date = 0;
|
||||
}
|
||||
else if (year > EPOCH + 135) {
|
||||
*date = 0xfdeefb80; /* XXX: EPOCH + 135 years */
|
||||
}
|
||||
else {
|
||||
int leap_year = LEAP_YEAR(year);
|
||||
msg_time_t ydays = YEAR_DAYS(year) - YEAR_DAYS(EPOCH);
|
||||
|
||||
#if 0
|
||||
printf("Year %d%s starts %ld = %d - %d days since epoch (%d)\n",
|
||||
year, leap_year ? " (leap year)" : "",
|
||||
ydays, YEAR_DAYS(year), YEAR_DAYS(EPOCH), EPOCH);
|
||||
#endif
|
||||
|
||||
*date = sec + 60 *
|
||||
(min + 60 *
|
||||
(hour + 24 *
|
||||
(day - 1 + mon * 30 + first_day_offset[mon] +
|
||||
(leap_year && mon > 2) + ydays)));
|
||||
}
|
||||
*ss = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**Encode RFC1123-date.
|
||||
*
|
||||
* The function msg_date_e() prints @e http-date in the <rfc1123-date>
|
||||
* format. The format is as follows:
|
||||
*
|
||||
* @code
|
||||
* rfc1123-date = wkday "," SP date SP time SP "GMT"
|
||||
* wkday = "Mon" | "Tue" | "Wed"
|
||||
* | "Thu" | "Fri" | "Sat" | "Sun"
|
||||
* date = 2DIGIT SP month SP 4DIGIT
|
||||
* ; day month year (e.g., 02 Jun 1982)
|
||||
* month = "Jan" | "Feb" | "Mar" | "Apr"
|
||||
* | "May" | "Jun" | "Jul" | "Aug"
|
||||
* | "Sep" | "Oct" | "Nov" | "Dec"
|
||||
* time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
|
||||
* ; 00:00:00 - 23:59:59
|
||||
* @endcode
|
||||
*
|
||||
* @param b buffer to print the date
|
||||
* @param bsiz size of the buffer
|
||||
* @param http_date seconds since 01 Jan 1900.
|
||||
*
|
||||
* @return The function msg_date_e() returns the size of the formatted date.
|
||||
*/
|
||||
issize_t msg_date_e(char b[], isize_t bsiz, msg_time_t http_date)
|
||||
{
|
||||
msg_time_t sec, min, hour, wkday, day, month, year;
|
||||
msg_time_t days_per_month, leap_year;
|
||||
|
||||
sec = http_date % 60; http_date /= 60;
|
||||
min = http_date % 60; http_date /= 60;
|
||||
hour = http_date % 24; http_date /= 24;
|
||||
|
||||
wkday = http_date % 7;
|
||||
day = http_date + YEAR_DAYS(EPOCH);
|
||||
year = EPOCH + http_date / 365;
|
||||
|
||||
for (;;) {
|
||||
if (day >= YEAR_DAYS(year + 1))
|
||||
year++;
|
||||
else if (day < YEAR_DAYS(year))
|
||||
year--;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
day -= YEAR_DAYS(year);
|
||||
leap_year = LEAP_YEAR(year);
|
||||
|
||||
month = 0, days_per_month = 31;
|
||||
while (day >= days_per_month) {
|
||||
day -= days_per_month;
|
||||
month++;
|
||||
days_per_month = days_per_months[month] + (leap_year && month == 2);
|
||||
}
|
||||
|
||||
return snprintf(b, bsiz, "%s, %02ld %s %04ld %02ld:%02ld:%02ld GMT",
|
||||
wkdays + wkday * 4, day + 1, months + month * 4,
|
||||
year, hour, min, sec);
|
||||
}
|
||||
|
||||
|
||||
/**Decode a delta-seconds.
|
||||
*
|
||||
* The function msg_delta_d() decodes a <delta-seconds> field.
|
||||
*
|
||||
* The <delta-seconds> is defined as follows:
|
||||
* @code
|
||||
* delta-seconds = 1*DIGIT
|
||||
* @endcode
|
||||
*
|
||||
* Note, however, that <delta-seconds> may not be larger than #MSG_TIME_MAX.
|
||||
*/
|
||||
issize_t msg_delta_d(char const **ss, msg_time_t *delta)
|
||||
{
|
||||
char const *s = *ss;
|
||||
|
||||
if (!is_digit(*s))
|
||||
return -1;
|
||||
|
||||
*delta = strtoul(*ss, (char **)ss, 10);
|
||||
skip_lws(ss);
|
||||
|
||||
return *ss - s;
|
||||
}
|
||||
|
||||
/**Encode @ref msg_delta_d() "<delta-seconds>" field.
|
||||
*/
|
||||
issize_t msg_delta_e(char b[], isize_t bsiz, msg_time_t delta)
|
||||
{
|
||||
return snprintf(b, bsiz, "%lu", (unsigned long)delta);
|
||||
}
|
||||
|
||||
/** Decode a HTTP date or delta
|
||||
*
|
||||
* Decode a @ref msg_date_d() "<http-date>" or
|
||||
* @ref msg_delta_d() "<delta-seconds>" field.
|
||||
*/
|
||||
issize_t msg_date_delta_d(char const **ss,
|
||||
msg_time_t *date,
|
||||
msg_time_t *delta)
|
||||
{
|
||||
if (delta && is_digit(**ss)) {
|
||||
return msg_delta_d(ss, delta);
|
||||
}
|
||||
else if (date && IS_TOKEN(**ss)) {
|
||||
return msg_date_d(ss, date);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 msg_parser
|
||||
* @file msg_generic.c
|
||||
* @brief Functions for generic headers
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Thu Jan 23 20:08:00 2003 ppessi
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sofia-sip/su_alloc.h>
|
||||
|
||||
#include "sofia-sip/msg.h"
|
||||
#include "sofia-sip/bnf.h"
|
||||
#include "sofia-sip/msg_parser.h"
|
||||
#include "sofia-sip/msg_header.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
|
||||
/**
|
||||
* Parse a generic header.
|
||||
*
|
||||
* The function msg_generic_d() parses a generic header structure.
|
||||
*
|
||||
* @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
|
||||
*
|
||||
* @retval 0 when successful,
|
||||
* @retval -1 upon an error.
|
||||
*/
|
||||
issize_t msg_generic_d(su_home_t *home,
|
||||
msg_header_t *h,
|
||||
char *s,
|
||||
isize_t slen)
|
||||
{
|
||||
h->sh_generic->g_string = s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a generic header.
|
||||
*
|
||||
* The function @c msg_generic_e encodes a generic header.
|
||||
*
|
||||
*/
|
||||
issize_t msg_generic_e(char b[], isize_t bsiz, msg_header_t const *h, int flags)
|
||||
{
|
||||
msg_generic_t const *g = h->sh_generic;
|
||||
size_t n = strlen(g->g_string);
|
||||
|
||||
if (bsiz > n)
|
||||
strcpy(b, g->g_string);
|
||||
|
||||
return (issize_t)n;
|
||||
}
|
||||
|
||||
/** Calculate the size of strings associated with a @c msg_generic_t object. */
|
||||
isize_t msg_generic_dup_xtra(msg_header_t const *h, isize_t offset)
|
||||
{
|
||||
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,
|
||||
isize_t xtra)
|
||||
{
|
||||
char *end = b + xtra;
|
||||
MSG_STRING_DUP(b, dst->sh_generic->g_string, src->sh_generic->g_string);
|
||||
assert(b <= end); (void)end;
|
||||
return b;
|
||||
}
|
||||
|
||||
issize_t msg_numeric_d(su_home_t *home,
|
||||
msg_header_t *h,
|
||||
char *s,
|
||||
isize_t slen)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
issize_t retval = msg_uint32_d(&s, &value);
|
||||
|
||||
h->sh_numeric->x_value = value;
|
||||
|
||||
if (*s)
|
||||
return -1;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
issize_t msg_numeric_e(char b[], isize_t bsiz, msg_header_t const *h, int flags)
|
||||
{
|
||||
uint32_t value = h->sh_numeric->x_value;
|
||||
|
||||
if (h->sh_numeric->x_value > 0xffffffff)
|
||||
return -1;
|
||||
|
||||
return snprintf(b, bsiz, "%lu", (unsigned long)value);
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Comma-separated list */
|
||||
|
||||
/** @typedef struct msg_list_s msg_list_t;
|
||||
*
|
||||
* Type for token list headers.
|
||||
*
|
||||
*/
|
||||
|
||||
issize_t msg_list_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen)
|
||||
{
|
||||
return msg_commalist_d(home, &s, &h->sh_list->k_items, NULL);
|
||||
}
|
||||
|
||||
issize_t msg_list_e(char b[], isize_t bsiz, msg_header_t const *h, int flags)
|
||||
{
|
||||
int compact = MSG_IS_COMPACT(flags);
|
||||
char *b0 = b, *end = b + bsiz;
|
||||
|
||||
MSG_COMMALIST_E(b, end, h->sh_list->k_items, compact);
|
||||
MSG_TERM_E(b, end);
|
||||
|
||||
return b - b0;
|
||||
}
|
||||
|
||||
/**@internal
|
||||
* 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.
|
||||
*/
|
||||
isize_t msg_list_dup_xtra(msg_header_t const *h, isize_t offset)
|
||||
{
|
||||
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,
|
||||
char *b,
|
||||
isize_t xtra)
|
||||
{
|
||||
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);
|
||||
|
||||
assert(b <= end); (void)end;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/** Append a list of constant items to a list.
|
||||
*
|
||||
* @retval 0 when successful
|
||||
* @retval -1 upon an error
|
||||
*/
|
||||
int msg_list_append_items(su_home_t *home,
|
||||
msg_list_t *k,
|
||||
msg_param_t const items[])
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (k == NULL) return -1;
|
||||
if (items == NULL) return 0;
|
||||
|
||||
for (i = 0; items[i]; i++) {
|
||||
if (msg_header_add_param(home, (msg_common_t *)k, items[i]) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Replace a list of constant items.
|
||||
*
|
||||
* @retval 0 when successful
|
||||
* @retval -1 upon an error
|
||||
*/
|
||||
int msg_list_replace_items(su_home_t *home,
|
||||
msg_list_t *k,
|
||||
msg_param_t const items[])
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (k == NULL) return -1;
|
||||
if (items == NULL) return 0;
|
||||
|
||||
for (i = 0; items[i]; i++) {
|
||||
if (msg_header_replace_item(home, (msg_common_t *)k, items[i]) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,534 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 msg_headers
|
||||
* @CFILE msg_header_copy.c
|
||||
*
|
||||
* Copying and duplicating headers structures.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Tue Jun 13 02:57:51 2000 ppessi
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sofia-sip/su_alloc.h>
|
||||
|
||||
#include <sofia-sip/su.h>
|
||||
|
||||
#include "msg_internal.h"
|
||||
#include "sofia-sip/msg.h"
|
||||
#include "sofia-sip/msg_parser.h"
|
||||
#include "sofia-sip/msg_header.h"
|
||||
|
||||
/** Calculate size of a parameter vector */
|
||||
static inline
|
||||
size_t msg_params_copy_xtra(msg_param_t const pp[], size_t offset)
|
||||
{
|
||||
size_t n = msg_params_count(pp);
|
||||
if (n) {
|
||||
MSG_STRUCT_SIZE_ALIGN(offset);
|
||||
offset += MSG_PARAMS_NUM(n + 1) * sizeof(pp[0]);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
/** Copy a vector of parameters */
|
||||
static inline
|
||||
char *msg_params_copy(char *b, size_t size,
|
||||
msg_param_t **dst,
|
||||
msg_param_t const src[])
|
||||
{
|
||||
size_t n = msg_params_count(src);
|
||||
|
||||
if (n) {
|
||||
MSG_STRUCT_ALIGN(b);
|
||||
*dst = memcpy(b, src, (n + 1) * sizeof(src[0]));
|
||||
b += MSG_PARAMS_NUM(n + 1) * sizeof(src[0]);
|
||||
}
|
||||
else {
|
||||
*dst = NULL;
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/**Copy a header object.
|
||||
*
|
||||
* The function @c msg_header_copy_as() shallowly copies a header object.
|
||||
*
|
||||
* @param home pointer to the memory home
|
||||
* @param hc header class for the copied header
|
||||
* @param src pointer to a header object
|
||||
*
|
||||
* @return
|
||||
* The function @c msg_header_copy_as() returns a pointer to the the shallow copy
|
||||
* of the header object, or @c NULL upon an error.
|
||||
*/
|
||||
static msg_header_t *msg_header_copy_one_as(su_home_t *home,
|
||||
msg_hclass_t *hc,
|
||||
msg_header_t const *src)
|
||||
{
|
||||
msg_header_t *h;
|
||||
size_t size = hc->hc_size, xtra;
|
||||
msg_param_t const *params;
|
||||
char *end;
|
||||
|
||||
if (hc->hc_params) {
|
||||
params = *(msg_param_t const **)((char const *)src + hc->hc_params);
|
||||
xtra = msg_params_copy_xtra(params, size) - size;
|
||||
}
|
||||
else {
|
||||
params = NULL;
|
||||
xtra = 0;
|
||||
}
|
||||
|
||||
if (!(h = msg_header_alloc(home, hc, (isize_t)xtra)))
|
||||
return NULL; /* error */
|
||||
|
||||
memcpy(&h->sh_data, &src->sh_data, size - offsetof(msg_common_t, h_data));
|
||||
h->sh_next = NULL;
|
||||
if (params) {
|
||||
msg_param_t **pparams = (msg_param_t **)((char *)h + hc->hc_params);
|
||||
end = msg_params_copy((char *)h + size, xtra, pparams, params);
|
||||
if (!end) {
|
||||
su_free(home, h);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
end = (char *)h + size;
|
||||
|
||||
assert(end == (char *)h + xtra + size);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/**Copy a list of header objects.
|
||||
*
|
||||
* The function @c msg_header_copy_as() shallowly copies a list of header
|
||||
* objects, and casts them to the given header class.
|
||||
*
|
||||
* @param home pointer to the memory home
|
||||
* @param hc header class
|
||||
* @param src pointer to a list of header objects to be copied
|
||||
*
|
||||
* @return The function @c msg_header_copy_as() returns a pointer to the
|
||||
* first of the copied msg header object(s), or @c NULL upon an error.
|
||||
*/
|
||||
msg_header_t *msg_header_copy_as(su_home_t *home,
|
||||
msg_hclass_t *hc,
|
||||
msg_header_t const *src)
|
||||
{
|
||||
msg_header_t *h, *rv = NULL, *prev = NULL;
|
||||
|
||||
if (src == NULL || src == MSG_HEADER_NONE)
|
||||
return NULL;
|
||||
|
||||
if (hc == NULL)
|
||||
hc = src->sh_class;
|
||||
|
||||
for (; src; src = src->sh_next, prev = h) {
|
||||
if (!(h = msg_header_copy_one_as(home, hc, src)))
|
||||
break;
|
||||
|
||||
if (!rv)
|
||||
rv = h;
|
||||
else
|
||||
prev->sh_next = h;
|
||||
}
|
||||
|
||||
if (src) {
|
||||
/* Copy was not successful, free all copied headers in list */
|
||||
for (;rv; rv = h) {
|
||||
h = rv->sh_next;
|
||||
su_free(home, rv);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** Copy a single header. */
|
||||
msg_header_t *msg_header_copy_one(su_home_t *home, msg_header_t const *src)
|
||||
{
|
||||
assert(MSG_HEADER_TEST(src));
|
||||
|
||||
if (!src || !src->sh_class)
|
||||
return NULL;
|
||||
|
||||
return msg_header_copy_one_as(home, src->sh_class, src);
|
||||
}
|
||||
|
||||
/** Copy a header list. */
|
||||
msg_header_t *msg_header_copy(su_home_t *home, msg_header_t const *src)
|
||||
{
|
||||
assert(MSG_HEADER_TEST(src));
|
||||
|
||||
if (!src || !src->sh_class)
|
||||
return NULL;
|
||||
|
||||
return msg_header_copy_as(home, src->sh_class, src);
|
||||
}
|
||||
|
||||
/** Duplicate a sigle header.
|
||||
*
|
||||
* Deeply copy a single header.
|
||||
*
|
||||
* @param home pointer to the memory home
|
||||
* @param src pointer to asingle header object to be copied
|
||||
*
|
||||
* @return Return a pointer to the
|
||||
* the duplicated msg header object(s), or @c NULL upon an error.
|
||||
*/
|
||||
msg_header_t *msg_header_dup_one(su_home_t *home,
|
||||
msg_header_t const *src)
|
||||
{
|
||||
msg_hclass_t *hc;
|
||||
size_t size, xtra;
|
||||
msg_header_t *h;
|
||||
char *end;
|
||||
|
||||
if (src == NULL || src == MSG_HEADER_NONE)
|
||||
return NULL;
|
||||
|
||||
hc = src->sh_class;
|
||||
|
||||
assert(hc);
|
||||
|
||||
size = hc->hc_size;
|
||||
xtra = hc->hc_dxtra(src, size) - size;
|
||||
|
||||
if (!(h = msg_header_alloc(home, hc, xtra)))
|
||||
return NULL;
|
||||
|
||||
if (!(end = hc->hc_dup_one(h, src, (char *)h + size, xtra))) {
|
||||
su_free(home, h);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (hc->hc_update)
|
||||
msg_header_update_params(h->sh_common, 1);
|
||||
|
||||
assert(end == (char *)h + size + xtra);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/** Duplicate a header as class @a hc.
|
||||
*
|
||||
* The function @c msg_header_dup_as() casts a list of header headers to
|
||||
* given type, and then deeply copies the list.
|
||||
*
|
||||
* @param home pointer to the memory home
|
||||
* @param hc header class
|
||||
* @param src pointer to a list of header objects to be copied
|
||||
*
|
||||
* @return The function @c msg_header_copy_as() returns a pointer to the
|
||||
* first of the copied msg header object(s), or @c NULL upon an error.
|
||||
*/
|
||||
msg_header_t *msg_header_dup_as(su_home_t *home, msg_hclass_t *hc,
|
||||
msg_header_t const *src)
|
||||
{
|
||||
msg_header_t *h, *rv = NULL, **prev;
|
||||
|
||||
if (src == NULL || src == MSG_HEADER_NONE)
|
||||
return NULL;
|
||||
|
||||
if (hc == NULL)
|
||||
hc = src->sh_class;
|
||||
|
||||
assert(hc);
|
||||
|
||||
for (prev = &rv; src; src = src->sh_next, prev = &h->sh_next) {
|
||||
size_t size = hc->hc_size;
|
||||
size_t xtra = hc->hc_dxtra(src, size) - size;
|
||||
char *end;
|
||||
|
||||
if (!(h = msg_header_alloc(home, hc, (isize_t)xtra)))
|
||||
break; /* error */
|
||||
|
||||
if (!rv)
|
||||
rv = h;
|
||||
|
||||
if (!(end = hc->hc_dup_one(h, src, (char *)h + size, xtra)))
|
||||
break; /* error */
|
||||
|
||||
if (hc->hc_update)
|
||||
msg_header_update_params(h->sh_common, 1);
|
||||
|
||||
assert(end == (char *)h + size + xtra);
|
||||
|
||||
*prev = h;
|
||||
}
|
||||
|
||||
if (src) {
|
||||
/* Copy was not successful, free all duplicated headers in list */
|
||||
for (;rv; rv = h) {
|
||||
h = rv->sh_next;
|
||||
su_free(home, rv);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** Duplicate a header list.
|
||||
*
|
||||
* The function @c msg_header_dup() deeply copies a list of message headers
|
||||
* objects.
|
||||
*
|
||||
* @param home pointer to the memory home
|
||||
* @param h pointer to a list of header objects to be copied
|
||||
*
|
||||
* @return The function @c msg_header_dup() returns a pointer to the first
|
||||
* of the copied message header object(s), or @c NULL upon an error.
|
||||
*/
|
||||
msg_header_t *msg_header_dup(su_home_t *home, msg_header_t const *h)
|
||||
{
|
||||
if (h == NULL || h == MSG_HEADER_NONE)
|
||||
return NULL;
|
||||
assert(MSG_HEADER_TEST(h));
|
||||
return msg_header_dup_as(home, h->sh_class, h);
|
||||
}
|
||||
|
||||
/** Calculate extra size of a plain header. */
|
||||
isize_t msg_default_dup_xtra(msg_header_t const *header, isize_t offset)
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**Duplicate a header object without external references.
|
||||
*
|
||||
* The function @c msg_default_dup_one() copies the contents of header
|
||||
* object @a src to @a h. The header object should not contain external
|
||||
* references (pointers).
|
||||
*
|
||||
* @param h pointer to newly allocated header object
|
||||
* @param src pointer to a header object to be duplicated
|
||||
* @param b memory buffer used to copy (not used)
|
||||
* @param xtra number bytes in buffer @a b (not used)
|
||||
*
|
||||
* @return The function @c msg_default_dup_one() returns a pointer to the
|
||||
* memory buffer @a b.
|
||||
*/
|
||||
char *msg_default_dup_one(msg_header_t *h,
|
||||
msg_header_t const *src,
|
||||
char *b,
|
||||
isize_t xtra)
|
||||
{
|
||||
memcpy(&h->sh_header_next[1],
|
||||
&src->sh_header_next[1],
|
||||
h->sh_class->hc_size - offsetof(msg_header_t, sh_header_next[1]));
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Copying or duplicating all headers in a message */
|
||||
|
||||
static int msg_copy_chain(msg_t *msg, msg_t const *copied);
|
||||
static int msg_dup_or_copy_all(msg_t *msg,
|
||||
msg_t const *original,
|
||||
msg_header_t *(*copy_one)(su_home_t *h,
|
||||
msg_header_t const *));
|
||||
|
||||
|
||||
/**Copy a message shallowly.
|
||||
*
|
||||
* @relatesalso msg_s
|
||||
*
|
||||
* Copy a message and the header structures. The copied message will share
|
||||
* all the strings with the original message. It will keep a reference to
|
||||
* the original message, and the original message is not destroyed until all
|
||||
* the copies have been destroyed.
|
||||
*
|
||||
* @param original message to be copied
|
||||
*
|
||||
* @retval pointer to newly copied message object when successful
|
||||
* @retval NULL upon an error
|
||||
*/
|
||||
msg_t *msg_copy(msg_t *original)
|
||||
{
|
||||
if (original) {
|
||||
msg_t *copy = msg_create(original->m_class, original->m_object->msg_flags);
|
||||
|
||||
if (copy) {
|
||||
if (original->m_chain
|
||||
? msg_copy_chain(copy, original) < 0
|
||||
: msg_dup_or_copy_all(copy, original, msg_header_copy_one) < 0) {
|
||||
msg_destroy(copy), copy = NULL;
|
||||
}
|
||||
else
|
||||
msg_set_parent(copy, original);
|
||||
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Copy header chain.
|
||||
*
|
||||
* @retval 0 when successful
|
||||
* @retval -1 upon an error
|
||||
*/
|
||||
static
|
||||
int msg_copy_chain(msg_t *msg, msg_t const *original)
|
||||
{
|
||||
su_home_t *home = msg_home(msg);
|
||||
msg_pub_t *dst = msg->m_object;
|
||||
msg_header_t **tail;
|
||||
msg_header_t *dh;
|
||||
msg_header_t const *sh;
|
||||
msg_header_t **hh;
|
||||
|
||||
tail = msg->m_tail;
|
||||
|
||||
for (sh = original->m_chain; sh; sh = (msg_header_t const *)sh->sh_succ) {
|
||||
hh = msg_hclass_offset(msg->m_class, dst, sh->sh_class);
|
||||
if (!hh)
|
||||
break;
|
||||
while (*hh)
|
||||
hh = &(*hh)->sh_next;
|
||||
|
||||
dh = msg_header_copy_one(home, sh);
|
||||
if (!dh)
|
||||
break;
|
||||
|
||||
dh->sh_prev = tail, *tail = dh, tail = &dh->sh_succ;
|
||||
|
||||
*hh = dh;
|
||||
}
|
||||
|
||||
msg->m_tail = tail;
|
||||
|
||||
if (sh)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/**Deep copy a message.
|
||||
*
|
||||
* @relatesalso msg_s
|
||||
*
|
||||
* Copy a message, the header structures and all the related strings. The
|
||||
* duplicated message does not share any (non-const) data with original.
|
||||
* Note that the cached representation (in h_data) is not copied.
|
||||
*
|
||||
* @param original message to be duplicated
|
||||
*
|
||||
* @retval pointer to newly duplicated message object when successful
|
||||
* @retval NULL upon an error
|
||||
*/
|
||||
msg_t *msg_dup(msg_t const *original)
|
||||
{
|
||||
if (original) {
|
||||
msg_t *dup = msg_create(original->m_class, original->m_object->msg_flags);
|
||||
|
||||
if (dup && msg_dup_or_copy_all(dup, original, msg_header_dup_one) < 0) {
|
||||
msg_destroy(dup), dup = NULL;
|
||||
}
|
||||
|
||||
return dup;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Copy a complete message, not keeping the header chain structure.
|
||||
*
|
||||
* @retval 0 when successful
|
||||
* @retval -1 upon an error
|
||||
*/
|
||||
static
|
||||
int msg_dup_or_copy_all(msg_t *msg,
|
||||
msg_t const *original,
|
||||
msg_header_t *(*copy_one)(su_home_t *h,
|
||||
msg_header_t const *))
|
||||
{
|
||||
su_home_t *home = msg_home(msg);
|
||||
msg_pub_t *dst = msg->m_object;
|
||||
|
||||
msg_pub_t const *src = original->m_object;
|
||||
msg_header_t * const *ssh;
|
||||
msg_header_t * const *end;
|
||||
msg_header_t const *sh;
|
||||
msg_header_t **hh;
|
||||
|
||||
msg_header_t *h;
|
||||
|
||||
assert(copy_one);
|
||||
|
||||
end = (msg_header_t**)((char *)src + src->msg_size);
|
||||
|
||||
for (ssh = &src->msg_request; ssh < end; ssh++) {
|
||||
sh = *ssh;
|
||||
if (!sh)
|
||||
continue;
|
||||
|
||||
hh = msg_hclass_offset(msg->m_class, dst, sh->sh_class);
|
||||
if (hh == NULL)
|
||||
return -1;
|
||||
|
||||
for (; sh; sh = sh->sh_next) {
|
||||
h = copy_one(home, sh);
|
||||
if (h == NULL)
|
||||
return -1;
|
||||
|
||||
if (*hh) {
|
||||
/* If there is multiple instances of single headers,
|
||||
put the extra headers into the list of erroneous headers */
|
||||
if (msg_is_single(h)) {
|
||||
msg_error_t **e;
|
||||
for (e = &dst->msg_error; *e; e = &(*e)->er_next)
|
||||
;
|
||||
*e = (msg_error_t *)h;
|
||||
continue;
|
||||
}
|
||||
|
||||
while (*hh)
|
||||
hh = &(*hh)->sh_next;
|
||||
}
|
||||
*hh = h;
|
||||
|
||||
if (msg_is_list(sh))
|
||||
/* Copy only first list entry */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 msg_headers
|
||||
* @CFILE msg_header_make.c
|
||||
*
|
||||
* Creating message headers from strings.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Fri Feb 23 14:06:34 2001 ppessi
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sofia-sip/su_alloc.h>
|
||||
|
||||
#include "sofia-sip/msg.h"
|
||||
#include "sofia-sip/bnf.h"
|
||||
#include "sofia-sip/msg_parser.h"
|
||||
#include "sofia-sip/msg_header.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(va_copy)
|
||||
/* Xyzzy */
|
||||
#elif defined(__va_copy)
|
||||
#define va_copy(dst, src) __va_copy((dst), (src))
|
||||
#else
|
||||
#define va_copy(dst, src) (memcpy(&(dst), &(src), sizeof (va_list)))
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/** Make a header from a value string. */
|
||||
msg_header_t *msg_header_make(su_home_t *home,
|
||||
msg_hclass_t *hc,
|
||||
char const *s)
|
||||
{
|
||||
size_t xtra;
|
||||
msg_header_t *h;
|
||||
int normal = hc->hc_name ||
|
||||
(hc->hc_hash != msg_payload_hash &&
|
||||
hc->hc_hash != msg_separator_hash &&
|
||||
hc->hc_hash != msg_error_hash);
|
||||
|
||||
if (s == NULL)
|
||||
return NULL;
|
||||
|
||||
/* For normal headers, strip LWS from both ends */
|
||||
if (normal)
|
||||
skip_lws(&s);
|
||||
xtra = strlen(s);
|
||||
if (normal)
|
||||
while (xtra > 0 && IS_LWS(s[xtra - 1]))
|
||||
xtra--;
|
||||
|
||||
h = msg_header_alloc(home, hc, xtra + 1);
|
||||
|
||||
if (h) {
|
||||
char *b = MSG_HEADER_DATA(h);
|
||||
|
||||
strncpy(b, s, xtra)[xtra] = 0;
|
||||
|
||||
if (hc->hc_parse(home, h, b, xtra) == -1) {
|
||||
/* Note: parsing function is responsible to free
|
||||
everything it has allocated (like parameter lists) */
|
||||
/* XXX - except header structures */
|
||||
su_free(home, h), h = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/** Make a MSG header with formatting provided. */
|
||||
msg_header_t *msg_header_vformat(su_home_t *home,
|
||||
msg_hclass_t *hc,
|
||||
char const *fmt,
|
||||
va_list ap)
|
||||
{
|
||||
msg_header_t *h;
|
||||
|
||||
int n;
|
||||
size_t xtra = 64; /* reasonable default */
|
||||
|
||||
/* Quick path */
|
||||
if (!fmt || !strchr(fmt, '%'))
|
||||
return msg_header_make(home, hc, fmt);
|
||||
|
||||
/* Another quickie */
|
||||
if (strcmp(fmt, "%s") == 0) {
|
||||
fmt = va_arg(ap, char const *);
|
||||
return msg_header_make(home, hc, fmt);
|
||||
}
|
||||
|
||||
if (!(h = msg_header_alloc(home, hc, xtra)))
|
||||
return NULL;
|
||||
|
||||
for (;;) {
|
||||
va_list aq;
|
||||
|
||||
va_copy(aq, ap);
|
||||
n = vsnprintf(MSG_HEADER_DATA(h), xtra, fmt, aq);
|
||||
va_end(aq);
|
||||
|
||||
if (n >= 0 && (size_t)n < xtra)
|
||||
break;
|
||||
|
||||
/* Try again with more space */
|
||||
su_free(home, h);
|
||||
|
||||
if (xtra >= INT_MAX)
|
||||
return NULL;
|
||||
|
||||
if (n >= 0)
|
||||
xtra = n + 1; /* precisely what is needed */
|
||||
else
|
||||
xtra *= 2; /* glibc 2.0 - twice the old size */
|
||||
|
||||
if (xtra > INT_MAX)
|
||||
xtra = INT_MAX;
|
||||
|
||||
if (!(h = msg_header_alloc(home, hc, xtra)))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (hc->hc_parse(home, h, MSG_HEADER_DATA(h), (size_t)n) == -1) {
|
||||
/* Note: parsing function is responsible to free
|
||||
everything it has allocated (like parameter lists) */
|
||||
su_free(home, h), h = NULL;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
msg_header_t *msg_header_format(su_home_t *home,
|
||||
msg_hclass_t *hc,
|
||||
char const *fmt,
|
||||
...)
|
||||
{
|
||||
msg_header_t *h;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
h = msg_header_vformat(home, hc, fmt, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
return h;
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MSG_INTERNAL_H
|
||||
/** Defined when <msg_internal.h> has been included. */
|
||||
#define MSG_INTERNAL_H
|
||||
|
||||
/**@IFILE msg_internal.h
|
||||
* @brief Abstract messages - internal interface
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Thu Jun 29 15:58:06 2000 ppessi
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef MSG_H
|
||||
#error "msg_internal.h" should be included before "msg.h"
|
||||
#endif
|
||||
|
||||
#include "sofia-sip/msg.h"
|
||||
#include "sofia-sip/msg_addr.h"
|
||||
#include "sofia-sip/msg_buffer.h"
|
||||
|
||||
#ifndef SU_ALLOC_H
|
||||
#include <sofia-sip/su_alloc.h>
|
||||
#endif
|
||||
|
||||
SOFIA_BEGIN_DECLS
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Types used when handling streaming */
|
||||
|
||||
typedef struct msg_buffer_s msg_buffer_t;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
struct msg_s {
|
||||
su_home_t m_home[1]; /**< Memory home */
|
||||
|
||||
msg_mclass_t const *m_class; /**< Message class */
|
||||
int m_oflags; /**< Original flags */
|
||||
|
||||
msg_pub_t *m_object; /**< Public view to parsed message */
|
||||
|
||||
size_t m_maxsize;/**< Maximum size */
|
||||
size_t m_size; /**< Total size of fragments */
|
||||
|
||||
msg_header_t *m_chain; /**< Fragment chain */
|
||||
msg_header_t **m_tail; /**< Tail of fragment chain */
|
||||
|
||||
msg_payload_t *m_chunk; /**< Incomplete payload fragment */
|
||||
|
||||
/* Parsing/printing buffer */
|
||||
struct msg_mbuffer_s {
|
||||
char *mb_data; /**< Pointer to data */
|
||||
usize_t mb_size; /**< Size of buffer */
|
||||
usize_t mb_used; /**< Used data */
|
||||
usize_t mb_commit; /**< Data committed to msg */
|
||||
unsigned mb_eos:1; /**< End-of-stream flag */
|
||||
unsigned :0;
|
||||
} m_buffer[1];
|
||||
|
||||
msg_buffer_t *m_stream; /**< User-provided buffers */
|
||||
size_t m_ssize; /**< Stream size */
|
||||
|
||||
unsigned short m_extract_err; /**< Bitmask of erroneous headers */
|
||||
/* Internal flags */
|
||||
unsigned m_set_buffer:1;/**< Buffer has been set */
|
||||
unsigned m_streaming:1; /**< Use streaming with message */
|
||||
unsigned m_prepared:1; /**< Prepared/not */
|
||||
unsigned :0;
|
||||
|
||||
msg_t *m_next; /**< Next message */
|
||||
|
||||
msg_t *m_parent; /**< Reference to a parent message */
|
||||
int m_refs; /**< Number of references to this message */
|
||||
|
||||
su_addrinfo_t m_addrinfo; /**< Message addressing info (protocol) */
|
||||
su_sockaddr_t m_addr[1]; /**< Message address */
|
||||
|
||||
int m_errno; /**< Errno */
|
||||
};
|
||||
|
||||
/** Buffer for message body. */
|
||||
struct msg_buffer_s {
|
||||
char *b_data; /**< Data - may contain NUL */
|
||||
size_t b_size; /**< Length of message payload */
|
||||
size_t b_used; /**< Used data */
|
||||
size_t b_avail; /**< Available data */
|
||||
int b_complete; /**< This buffer completes the message */
|
||||
msg_buffer_t *b_next; /**< Next buffer */
|
||||
msg_payload_t *b_chunks; /**< List of body chunks */
|
||||
};
|
||||
|
||||
/** Maximum size when streaming. */
|
||||
#define MSG_SSIZE_MAX (USIZE_MAX)
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Header-kind predicate functions. */
|
||||
static inline int msg_is_single(msg_header_t const *h)
|
||||
{
|
||||
return h->sh_class->hc_kind == msg_kind_single;
|
||||
}
|
||||
|
||||
static inline int msg_is_prepend(msg_header_t const *h)
|
||||
{
|
||||
return h->sh_class->hc_kind == msg_kind_prepend;
|
||||
}
|
||||
|
||||
static inline int msg_is_append(msg_header_t const *h)
|
||||
{
|
||||
return
|
||||
h->sh_class->hc_kind == msg_kind_append ||
|
||||
h->sh_class->hc_kind == msg_kind_apndlist;
|
||||
}
|
||||
|
||||
static inline int msg_is_list(msg_header_t const *h)
|
||||
{
|
||||
return h->sh_class->hc_kind == msg_kind_list;
|
||||
}
|
||||
|
||||
static inline int msg_is_special(msg_header_t const *h)
|
||||
{
|
||||
return h->sh_class->hc_hash < 0;
|
||||
}
|
||||
|
||||
SOFIA_END_DECLS
|
||||
|
||||
#endif /* MSG_INTERNAL_H */
|
||||
@@ -0,0 +1,387 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 msg_parser
|
||||
* @CFILE msg_mclass.c
|
||||
*
|
||||
* Message factory object.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Wed Jun 5 14:34:24 2002 ppessi
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <sofia-sip/su_tagarg.h>
|
||||
|
||||
#include <sofia-sip/su.h>
|
||||
#include <sofia-sip/su_alloc.h>
|
||||
|
||||
#include "msg_internal.h"
|
||||
#include "sofia-sip/msg_parser.h"
|
||||
#include "sofia-sip/msg_mclass.h"
|
||||
#include "sofia-sip/msg_mclass_hash.h"
|
||||
|
||||
/** Clone a message class.
|
||||
*
|
||||
* @relatesalso msg_mclass_s
|
||||
*
|
||||
* The function msg_mclass_clone() makes a copy of message class object @a
|
||||
* old. It is possible to resize the hash table by giving a non-zero @a
|
||||
* newsize. If @a newsize is 0, the size of hash table is not changed. If @a
|
||||
* empty is true, the copied message class object will not recognize any
|
||||
* headers. This is useful if more fine-grained control of parsing process
|
||||
* is required, for instance.
|
||||
*
|
||||
* @param[in] old pointer to the message class object to be copied
|
||||
* @param[in] newsize size of hash table in the copied object
|
||||
* @param[in] empty if true, resulting copy does not contain any headers
|
||||
*
|
||||
* @return
|
||||
* The function msg_mclass_clone() returns a pointer to a newly
|
||||
* copied message class object, or NULL upon an error.
|
||||
* The returned message class object can be freed with free().
|
||||
*
|
||||
* @ERRORS
|
||||
* @ERROR ENOMEM
|
||||
* A memory allocation failed.
|
||||
* @ERROR EINVAL
|
||||
* The function was given invalid arguments.
|
||||
*
|
||||
* @note The empty parser can handle request/status line. All headers are
|
||||
* put into list of unknown headers (unless they are malformed, and they are
|
||||
* put into list of erronous headers). However, SIP, RTSP, and HTTP
|
||||
* protocols all require that the parser recognizes @b Content-Length header
|
||||
* before they can extract the message body from the data received from
|
||||
* network.
|
||||
*
|
||||
*/
|
||||
msg_mclass_t *msg_mclass_clone(msg_mclass_t const *old, int newsize, int empty)
|
||||
{
|
||||
size_t size, shortsize;
|
||||
msg_mclass_t *mc;
|
||||
int identical;
|
||||
unsigned short i;
|
||||
|
||||
if (newsize == 0)
|
||||
newsize = old->mc_hash_size;
|
||||
|
||||
if (newsize < old->mc_hash_used ||
|
||||
(unsigned)newsize > USHRT_MAX / sizeof(msg_header_t *)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size = offsetof(msg_mclass_t, mc_hash[newsize]);
|
||||
if (old->mc_short)
|
||||
shortsize = MC_SHORT_SIZE * (sizeof old->mc_short[0]);
|
||||
else
|
||||
shortsize = 0;
|
||||
mc = malloc(size + shortsize);
|
||||
identical = newsize == old->mc_hash_size && !empty;
|
||||
|
||||
if (mc) {
|
||||
if (!identical) {
|
||||
memcpy(mc, old, offsetof(msg_mclass_t, mc_hash));
|
||||
memset(mc->mc_hash, 0, size - offsetof(msg_mclass_t, mc_hash));
|
||||
mc->mc_short = NULL;
|
||||
mc->mc_hash_size = newsize;
|
||||
mc->mc_hash_used = 0;
|
||||
for (i = 0; !empty && i < old->mc_hash_size; i++) {
|
||||
msg_mclass_insert(mc, &old->mc_hash[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
memcpy(mc, old, size);
|
||||
mc->mc_short = NULL;
|
||||
}
|
||||
|
||||
if (shortsize) {
|
||||
if (empty)
|
||||
mc->mc_short = memset((char *)mc + size, 0, shortsize);
|
||||
else
|
||||
mc->mc_short = memcpy((char *)mc + size, old->mc_short, shortsize);
|
||||
}
|
||||
}
|
||||
|
||||
return mc;
|
||||
}
|
||||
|
||||
/**Add a new header to the message class.
|
||||
*
|
||||
* @relatesalso msg_mclass_s
|
||||
*
|
||||
* Insert a header class @a hc to the message class object @a mc. If the
|
||||
* given @a offset of the header in @ref msg_pub_t "public message
|
||||
* structure" is zero, the function extends the public message structure in
|
||||
* order to store newly inserted header there.
|
||||
*
|
||||
* @param[in,out] mc pointer to a message class object
|
||||
* @param[in] hc pointer to a header class object
|
||||
* @param[in] offset offset of the header in
|
||||
* @ref msg_pub_t "public message structure"
|
||||
*
|
||||
* If the @a offset is 0, the msg_mclass_insert_header() increases size of
|
||||
* the public message structure and places the header at the end of message.
|
||||
*
|
||||
* @return Number of collisions in hash table, or -1 upon an error.
|
||||
*
|
||||
* @deprecated Use msg_mclass_insert_with_mask() instead.
|
||||
*/
|
||||
int msg_mclass_insert_header(msg_mclass_t *mc,
|
||||
msg_hclass_t *hc,
|
||||
unsigned short offset)
|
||||
{
|
||||
msg_href_t hr[1];
|
||||
|
||||
if (mc == NULL || hc == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (msg_hclass_offset(mc, NULL, hc))
|
||||
return (void)(errno = EEXIST), -1;
|
||||
|
||||
if (offset == 0)
|
||||
offset = mc->mc_msize, mc->mc_msize += sizeof(msg_header_t *);
|
||||
|
||||
assert(offset < mc->mc_msize);
|
||||
|
||||
hr->hr_class = hc;
|
||||
hr->hr_offset = offset;
|
||||
|
||||
return msg_mclass_insert(mc, hr);
|
||||
}
|
||||
|
||||
/**Add a new header to the message class.
|
||||
*
|
||||
* @relatesalso msg_mclass_s
|
||||
*
|
||||
* Insert a header class @a hc to the message class @a mc. If the given @a
|
||||
* offset of the header in @ref msg_pub_t "public message structure" is
|
||||
* zero, extend the size of the public message structure in order to store
|
||||
* headers at the end of structure.
|
||||
*
|
||||
* @param[in,out] mc pointer to a message class
|
||||
* @param[in] hc pointer to a header class
|
||||
* @param[in] offset offset of the header in
|
||||
* @ref msg_pub_t "public message structure"
|
||||
* @param[in] flags classification flags for the header
|
||||
*
|
||||
* @return Number of collisions in hash table, or -1 upon an error.
|
||||
*/
|
||||
int msg_mclass_insert_with_mask(msg_mclass_t *mc,
|
||||
msg_hclass_t *hc,
|
||||
unsigned short offset,
|
||||
unsigned short flags)
|
||||
{
|
||||
msg_href_t hr[1];
|
||||
|
||||
if (mc == NULL || hc == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (msg_hclass_offset(mc, NULL, hc))
|
||||
return (void)(errno = EEXIST), -1;
|
||||
|
||||
if (offset == 0)
|
||||
offset = mc->mc_msize, mc->mc_msize += sizeof(msg_header_t *);
|
||||
|
||||
assert(offset < mc->mc_msize);
|
||||
|
||||
hr->hr_class = hc;
|
||||
hr->hr_offset = offset;
|
||||
hr->hr_flags = flags;
|
||||
|
||||
return msg_mclass_insert(mc, hr);
|
||||
}
|
||||
|
||||
/** Add a header reference to the message class.
|
||||
*
|
||||
* @relatesalso msg_mclass_s
|
||||
*
|
||||
* @param[in,out] mc pointer to a message class object
|
||||
* @param[in] hr header reference object
|
||||
*
|
||||
* @return Number of collisions in hash table, or -1 upon an error.
|
||||
*/
|
||||
int msg_mclass_insert(msg_mclass_t *mc, msg_href_t const *hr)
|
||||
{
|
||||
int j, j0;
|
||||
int N;
|
||||
int collisions = 0;
|
||||
msg_hclass_t *hc;
|
||||
|
||||
if (mc == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hr == NULL || (hc = hr->hr_class) == NULL)
|
||||
return 0;
|
||||
|
||||
/* Add short form */
|
||||
if (mc->mc_short && hc->hc_short[0]) {
|
||||
char compact = hc->hc_short[0];
|
||||
msg_href_t *shorts = (msg_href_t *)mc->mc_short;
|
||||
|
||||
if (compact < 'a' || compact > 'z')
|
||||
return -1;
|
||||
|
||||
if (shorts[compact - 'a'].hr_class &&
|
||||
shorts[compact - 'a'].hr_class != hc)
|
||||
return -1;
|
||||
|
||||
shorts[compact - 'a'] = *hr;
|
||||
}
|
||||
|
||||
N = mc->mc_hash_size;
|
||||
j0 = msg_header_name_hash(hc->hc_name, NULL) % N;
|
||||
|
||||
for (j = j0; mc->mc_hash[j].hr_class; ) {
|
||||
collisions++;
|
||||
if (mc->mc_hash[j].hr_class == hc)
|
||||
return -1;
|
||||
j = (j + 1) % N;
|
||||
if (j == j0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
mc->mc_hash[j] = hr[0];
|
||||
mc->mc_hash_used++;
|
||||
|
||||
return collisions;
|
||||
}
|
||||
|
||||
/** Calculate length of line ending (0, 1 or 2). @internal */
|
||||
#define CRLF_TEST(cr, lf) ((cr) == '\r' ? ((lf) == '\n') + 1 : (cr)=='\n')
|
||||
|
||||
/**Search for a header class.
|
||||
*
|
||||
* @relatesalso msg_mclass_s
|
||||
*
|
||||
* The function msg_find_hclass() searches for a header class from a message
|
||||
* class based on the contents of the header to be parsed. The buffer @a s
|
||||
* should point to the first character in the header name.
|
||||
*
|
||||
* @param[in] mc message class object
|
||||
* @param[in] s header contents
|
||||
* @param[out] return_start_of_content start of header content (may be NULL)
|
||||
*
|
||||
* @return The function msg_find_hclass() returns a pointer to a header
|
||||
* reference structure. A pointer to a header reference for unknown headers
|
||||
* is returned, if the header is not included in the message class.
|
||||
*
|
||||
* @par
|
||||
* The return-value parameter @a return_start_of_content will contain the
|
||||
* start of the header contents within @a s, or 0 upon an error parsing the
|
||||
* header name and following colon.
|
||||
*
|
||||
* @par
|
||||
* Upon a fatal error, a NULL pointer is returned.
|
||||
*/
|
||||
msg_href_t const *msg_find_hclass(msg_mclass_t const *mc,
|
||||
char const *s,
|
||||
isize_t *return_start_of_content)
|
||||
{
|
||||
msg_href_t const *hr;
|
||||
short i, N, m;
|
||||
isize_t len;
|
||||
|
||||
assert(mc);
|
||||
|
||||
N = mc->mc_hash_size;
|
||||
|
||||
i = msg_header_name_hash(s, &len) % N;
|
||||
|
||||
if (len == 0 || len > HC_LEN_MAX) {
|
||||
if (return_start_of_content)
|
||||
*return_start_of_content = 0;
|
||||
return mc->mc_error;
|
||||
}
|
||||
|
||||
m = (short)len;
|
||||
|
||||
if (m == 1 && mc->mc_short) {
|
||||
short c = s[0];
|
||||
if (c >= 'a' && c <= 'z')
|
||||
hr = &mc->mc_short[c - 'a'];
|
||||
else if (c >= 'A' && c <= 'Z')
|
||||
hr = &mc->mc_short[c - 'A'];
|
||||
else
|
||||
hr = mc->mc_unknown;
|
||||
|
||||
if (hr->hr_class == NULL)
|
||||
hr = mc->mc_unknown;
|
||||
}
|
||||
else {
|
||||
msg_hclass_t *hc;
|
||||
|
||||
/* long form */
|
||||
for (hr = NULL; (hc = mc->mc_hash[i].hr_class); i = (i + 1) % N) {
|
||||
if (m == hc->hc_len && strncasecmp(s, hc->hc_name, m) == 0) {
|
||||
hr = &mc->mc_hash[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hr == NULL)
|
||||
hr = mc->mc_unknown;
|
||||
}
|
||||
|
||||
if (!return_start_of_content) /* Just header name */
|
||||
return hr;
|
||||
|
||||
if (s[len] == ':') { /* Fast path */
|
||||
*return_start_of_content = ++len;
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (IS_LWS(s[len])) {
|
||||
int crlf = 0;
|
||||
do {
|
||||
len += span_ws(s + len + crlf) + crlf; /* Skip lws before colon */
|
||||
crlf = CRLF_TEST(s[len], s[len + 1]);
|
||||
}
|
||||
while (IS_WS(s[len + crlf]));
|
||||
}
|
||||
|
||||
if (s[len++] != ':') /* Colon is required in header */
|
||||
len = 0;
|
||||
|
||||
*return_start_of_content = len;
|
||||
|
||||
return hr;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,70 @@
|
||||
/**@ingroup msg_mime
|
||||
* @IFILE msg_mime_table.c.in
|
||||
*
|
||||
* Template for <msg_mime_table.c>.
|
||||
*
|
||||
* @date Created: Wed Feb 21 11:01:45 2001 ppessi
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 msg_mime
|
||||
*
|
||||
* @CFILE msg_mime_table.c
|
||||
* @brief Parser table used for testing.
|
||||
*
|
||||
* #AUTO#
|
||||
*
|
||||
* This file is generated from template <msg_mime_table.c.in>.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sofia-sip/msg_mime.h>
|
||||
#include <sofia-sip/msg_mime_protos.h>
|
||||
|
||||
#include <sofia-sip/msg_mclass.h>
|
||||
|
||||
#define msg_multipart_extract_body NULL
|
||||
|
||||
#define msg_request_class NULL
|
||||
#define mp_request mp_common
|
||||
|
||||
#define msg_status_class NULL
|
||||
#define mp_status mp_common
|
||||
|
||||
#define msg_multipart_update NULL
|
||||
|
||||
#define MSG_MULTIPART_HCLASS \
|
||||
MSG_HEADER_CLASS(msg_, multipart, NULL, "", mp_common, append, \
|
||||
msg_multipart, msg_multipart)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 test_msg
|
||||
* @CFILE msg_name_hash.c
|
||||
*
|
||||
* Calculate hash for given header name.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Tue Aug 20 16:27:01 EEST 2002 ppessi
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <sofia-sip/su_alloc.h>
|
||||
|
||||
#include <sofia-sip/msg_mclass_hash.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (!argv[1] || argv[2]) {
|
||||
fprintf(stderr, "usage: msg_name_hash Header-Name\n");
|
||||
exit(1);
|
||||
}
|
||||
printf("%d\n", msg_header_name_hash(argv[1], NULL));
|
||||
exit(0);
|
||||
}
|
||||
@@ -0,0 +1,512 @@
|
||||
#! /usr/bin/env awk
|
||||
#
|
||||
# This script recreates C files containing header-specific boilerplate stuff
|
||||
# using the given list of headers (usually obtained from the master structure).
|
||||
#
|
||||
# It can also create a parser table.
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
#
|
||||
# This file is part of the Sofia-SIP package
|
||||
#
|
||||
# Copyright (C) 2005 Nokia Corporation.
|
||||
#
|
||||
# Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# 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
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
#
|
||||
# Contributor(s): Pekka.Pessi@nokia.com.
|
||||
#
|
||||
# Created: Fri Apr 6 12:59:59 2001 ppessi
|
||||
#
|
||||
|
||||
BEGIN {
|
||||
"date '+%a %b %e %H:%M:%S %Y'" | getline date;
|
||||
|
||||
ascii = \
|
||||
" " \
|
||||
" !\"#$%&'()*+,-./0123456789:;<=>?" \
|
||||
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" \
|
||||
"`abcdefghijklmnopqrstuvwxyz{|}~";
|
||||
lower_case = "abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
N=0;
|
||||
# Initialize these as arrays
|
||||
split("", symbols);
|
||||
split("", names);
|
||||
split("", comments);
|
||||
split("", hashes);
|
||||
split("", NAMES);
|
||||
split("", Comments);
|
||||
split("", COMMENTS);
|
||||
|
||||
# indexed by the C name of the header
|
||||
split("", Since); # Non-NUL if extra
|
||||
split("", Extra); # Offset in extra headers
|
||||
|
||||
template="";
|
||||
template1="";
|
||||
template2="";
|
||||
template3="";
|
||||
prefix="";
|
||||
tprefix="";
|
||||
extra=0;
|
||||
failed=0;
|
||||
success=0;
|
||||
|
||||
extra_struct = "msg_pub_extra";
|
||||
|
||||
ERRNO="error";
|
||||
}
|
||||
|
||||
function name_hash (name)
|
||||
{
|
||||
hash = 0;
|
||||
|
||||
len = split(name, chars, "");
|
||||
|
||||
for (i = 1; i <= len; i++) {
|
||||
c = tolower(chars[i]);
|
||||
hash = (38501 * (hash + index(ascii, c))) % 65536;
|
||||
}
|
||||
|
||||
if (0) {
|
||||
# Test that hash algorithm above agrees with the C version
|
||||
pipe = ("../msg/msg_name_hash " name);
|
||||
pipe | getline;
|
||||
close(pipe);
|
||||
if (hash != $0) {
|
||||
print name ": " hash " != " $0 > "/dev/stderr";
|
||||
}
|
||||
}
|
||||
|
||||
return hash "";
|
||||
}
|
||||
|
||||
#
|
||||
# Replace magic patterns in template p with header-specific values
|
||||
#
|
||||
function protos (name, comment, hash, since)
|
||||
{
|
||||
NAME=toupper(name);
|
||||
sub(/.*[\/][*][*][<][ ]*/, "", comment);
|
||||
sub(/[ ]*[*][\/].*/, "", comment);
|
||||
sub(/[ ]+/, " ", comment);
|
||||
|
||||
short = match(comment, /[(][a-z][)]/);
|
||||
if (short) {
|
||||
short = substr(comment, short + 1, 1);
|
||||
sub(/ *[(][a-z][)]/, "", comment);
|
||||
shorts[index(lower_case, short)] = name;
|
||||
}
|
||||
|
||||
do_hash = hash == 0;
|
||||
|
||||
if (do_hash) {
|
||||
split(comment, parts, " ");
|
||||
name2 = tolower(parts[1]);
|
||||
gsub(/-/, "_", name2);
|
||||
if (name2 != name && name2 != tprefix "_" name) {
|
||||
print name " mismatch with " comment " (" real ")" > "/dev/stderr";
|
||||
}
|
||||
|
||||
hash = name_hash(parts[1]);
|
||||
|
||||
hashed[name] = hash;
|
||||
|
||||
if (comment !~ /header/) {
|
||||
comment = comment " header";
|
||||
}
|
||||
}
|
||||
|
||||
Comment = comment;
|
||||
if (!do_hash) {
|
||||
comment = tolower(comment);
|
||||
}
|
||||
COMMENT = toupper(comment);
|
||||
|
||||
# Store the various forms into an array for the footer processing
|
||||
N++;
|
||||
hashes[N] = hash;
|
||||
names[N] = name;
|
||||
NAMES[N] = NAME;
|
||||
comments[N] = comment;
|
||||
Comments[N] = comment;
|
||||
COMMENTS[N] = COMMENT;
|
||||
|
||||
symbols[name] = comment;
|
||||
if (since) {
|
||||
Since[name] = since;
|
||||
Extra[name] = extra++;
|
||||
}
|
||||
|
||||
if (PR) {
|
||||
replace(template, hash, name, NAME, comment, Comment, COMMENT, since);
|
||||
replace(template1, hash, name, NAME, comment, Comment, COMMENT, since);
|
||||
replace(template2, hash, name, NAME, comment, Comment, COMMENT, since);
|
||||
replace(template3, hash, name, NAME, comment, Comment, COMMENT, since);
|
||||
}
|
||||
}
|
||||
|
||||
function replace (p, hash, name, NAME, comment, Comment, COMMENT, since)
|
||||
{
|
||||
#
|
||||
# Replace various forms of header name in template, print it out
|
||||
#
|
||||
if (p) {
|
||||
gsub(/#hash#/, hash, p);
|
||||
gsub(/#xxxxxx#/, name, p);
|
||||
gsub(/#XXXXXX#/, NAME, p);
|
||||
gsub(/#xxxxxxx_xxxxxxx#/, comment, p);
|
||||
gsub(/#Xxxxxxx_Xxxxxxx#/, Comment, p);
|
||||
gsub(/#XXXXXXX_XXXXXXX#/, COMMENT, p);
|
||||
|
||||
if (since) {
|
||||
gsub(/#version#/, since, p);
|
||||
}
|
||||
else {
|
||||
# Remove line with #version#
|
||||
gsub(/\n[^\n]*#version#[^\n]*\n/, "\n", p);
|
||||
}
|
||||
|
||||
print p > PR;
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Repeat each line in the footer containing the magic replacement
|
||||
# pattern with a instance of all headers
|
||||
#
|
||||
function process_footer (text)
|
||||
{
|
||||
if (!match(tolower(text), /#(xxxxxx(x_xxxxxxx)?|hash)#/)) {
|
||||
n = length(text);
|
||||
while (substr(text, n) == "\n") {
|
||||
n = n - 1;
|
||||
text = substr(text, 1, n);
|
||||
}
|
||||
if (n > 0)
|
||||
print text > PR;
|
||||
return;
|
||||
}
|
||||
|
||||
n = split(text, lines, RS);
|
||||
|
||||
for (i = 1; i <= n; i++) {
|
||||
l = lines[i];
|
||||
if (match(tolower(l), /#(xxxxxx(x_xxxxxxx)?|hash)#/)) {
|
||||
for (j = 1; j <= N; j++) {
|
||||
l = lines[i];
|
||||
gsub(/#hash#/, hashes[j], l);
|
||||
gsub(/#xxxxxxx_xxxxxxx#/, comments[j], l);
|
||||
gsub(/#Xxxxxxx_Xxxxxxx#/, Comments[j], l);
|
||||
gsub(/#XXXXXXX_XXXXXXX#/, COMMENTS[j], l);
|
||||
gsub(/#xxxxxx#/, names[j], l);
|
||||
gsub(/#XXXXXX#/, NAMES[j], l);
|
||||
print l > PR;
|
||||
}
|
||||
} else {
|
||||
print l > PR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Read flags used with headers
|
||||
#
|
||||
function read_header_flags (flagfile, line, tokens, name, value)
|
||||
{
|
||||
while ((getline line < flagfile) > 0) {
|
||||
sub(/^[ \t]+/, "", line);
|
||||
sub(/[ \t]+$/, "", line);
|
||||
if (line ~ /^#/ || line ~ /^$/)
|
||||
continue;
|
||||
|
||||
split(line, tokens, /[ \t]*=[ \t]*/);
|
||||
name = tolower(tokens[1]);
|
||||
gsub(/-/, "_", name);
|
||||
gsub(/,/, " ", name);
|
||||
# print "FLAG: " name " = " tokens[2]
|
||||
|
||||
if (header_flags[name]) {
|
||||
print flagfile ": already defined " tokens[1];
|
||||
}
|
||||
else if (!symbols[name]) {
|
||||
print flagfile ": unknown header \"" tokens[1] "\"";
|
||||
}
|
||||
else {
|
||||
header_flags[name] = tokens[2];
|
||||
}
|
||||
}
|
||||
close(flagfile);
|
||||
}
|
||||
|
||||
#
|
||||
# Read in templates
|
||||
#
|
||||
function templates ()
|
||||
{
|
||||
if (!auto) {
|
||||
auto = FILENAME;
|
||||
|
||||
if (!prefix) { prefix = module; }
|
||||
if (!tprefix) { tprefix = prefix; }
|
||||
|
||||
sub(/.*\//, "", auto);
|
||||
auto = "This file is automatically generated from <" auto "> by msg_parser.awk.";
|
||||
|
||||
if (PR) {
|
||||
if (TEMPLATE == "") { TEMPLATE = PR ".in"; }
|
||||
RS0=RS; RS="\f\n";
|
||||
if ((getline theader < TEMPLATE) < 0) {
|
||||
print ( TEMPLATE ": " ERRNO );
|
||||
failed=1;
|
||||
exit(1);
|
||||
}
|
||||
getline header < TEMPLATE;
|
||||
getline template < TEMPLATE;
|
||||
getline footer < TEMPLATE;
|
||||
|
||||
if (TEMPLATE1) {
|
||||
if ((getline dummy < TEMPLATE1) < 0) {
|
||||
print(TEMPLATE1 ": " ERRNO);
|
||||
failed=1;
|
||||
exit(1);
|
||||
}
|
||||
getline dummy < TEMPLATE1;
|
||||
getline template1 < TEMPLATE1;
|
||||
getline dummy < TEMPLATE1;
|
||||
}
|
||||
|
||||
if (TEMPLATE2) {
|
||||
if ((getline dummy < TEMPLATE2) < 0) {
|
||||
print( TEMPLATE2 ": " ERRNO );
|
||||
failed=1;
|
||||
exit(1);
|
||||
}
|
||||
getline dummy < TEMPLATE2;
|
||||
getline template2 < TEMPLATE2;
|
||||
getline dummy < TEMPLATE2;
|
||||
}
|
||||
|
||||
if (TEMPLATE3) {
|
||||
if ((getline dummy < TEMPLATE3) < 0) {
|
||||
print( TEMPLATE3 ": " ERRNO );
|
||||
failed=1;
|
||||
exit(1);
|
||||
}
|
||||
getline dummy < TEMPLATE3;
|
||||
getline template3 < TEMPLATE3;
|
||||
getline dummy < TEMPLATE3;
|
||||
}
|
||||
|
||||
sub(/.*[\/]/, "", TEMPLATE);
|
||||
gsub(/#AUTO#/, auto, header);
|
||||
gsub(/#DATE#/, "@date Generated: " date, header);
|
||||
if (PACKAGE_NAME) gsub(/#PACKAGE_NAME#/, PACKAGE_NAME, header);
|
||||
if (PACKAGE_VERSION) gsub(/#PACKAGE_VERSION#/, PACKAGE_VERSION, header);
|
||||
print header > PR;
|
||||
|
||||
RS=RS0;
|
||||
}
|
||||
|
||||
if (!NO_FIRST) {
|
||||
protos("request", "/**< Request line */", -1);
|
||||
protos("status", "/**< Status line */", -2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/^#### EXTRA HEADER LIST STARTS HERE ####$/ { HLIST=1; templates(); }
|
||||
HLIST && /^[a-z]/ { protos($1, $0, 0, $2); headers[total++] = $1; }
|
||||
/^#### EXTRA HEADER LIST ENDS HERE ####$/ { HLIST=0; }
|
||||
|
||||
|
||||
/^ *\/\* === Headers start here \*\// { in_header_list=1; templates(); }
|
||||
/^ *\/\* === Headers end here \*\// { in_header_list=0; }
|
||||
|
||||
PT && /^ *\/\* === Hash headers end here \*\// { in_header_list=0;}
|
||||
|
||||
in_header_list && /^ (sip|rtsp|http|msg|mp)_[a-z_0-9]+_t/ {
|
||||
n=$0
|
||||
sub(/;.*$/, "", n);
|
||||
sub(/^ *(sip|rtsp|http|msg|mp)_[a-z0-9_]*_t[ ]*/, "", n);
|
||||
sub(/^[*](sip|rtsp|http|msg|mp)_/, "", n);
|
||||
|
||||
if ($0 !~ /[\/][*][*][<]/) {
|
||||
getline;
|
||||
}
|
||||
if ($0 !~ /[\/][*][*][<]/) {
|
||||
printf "msg_protos.awk: header %s is malformed\n", n;
|
||||
failed=1;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
if (!NO_MIDDLE)
|
||||
protos(n, $0, 0);
|
||||
|
||||
headers[total++] = n;
|
||||
}
|
||||
|
||||
END {
|
||||
if (failed) { exit };
|
||||
|
||||
if (!NO_LAST) {
|
||||
protos("unknown", "/**< Unknown headers */", -3);
|
||||
protos("error", "/**< Erroneous headers */", -4);
|
||||
protos("separator", "/**< Separator line between headers and payload */", -5);
|
||||
protos("payload", "/**< Message payload */", -6);
|
||||
if (multipart)
|
||||
protos("multipart", "/**< Multipart payload */", -7);
|
||||
}
|
||||
|
||||
if (PR) {
|
||||
process_footer(footer);
|
||||
}
|
||||
else if (PT) {
|
||||
if (FLAGFILE)
|
||||
read_header_flags(FLAGFILE);
|
||||
|
||||
if (TEMPLATE == "") { TEMPLATE = PT ".in"; }
|
||||
RS0=RS; RS="\n";
|
||||
getline theader < TEMPLATE;
|
||||
getline header < TEMPLATE;
|
||||
getline template < TEMPLATE;
|
||||
getline footer < TEMPLATE;
|
||||
RS=RS0;
|
||||
|
||||
module_struct = module "_t";
|
||||
|
||||
sub(/.*[\/]/, "", TEMPLATE);
|
||||
gsub(/#AUTO#/, auto, header);
|
||||
gsub(/#DATE#/, "@date Generated: " date, header);
|
||||
print header > PT;
|
||||
|
||||
if (MC_SHORT_SIZE) {
|
||||
printf("static msg_href_t const " \
|
||||
"%s_short_forms[MC_SHORT_SIZE] = \n{\n",
|
||||
module) > PT;
|
||||
|
||||
for (i = 1; i <= MC_SHORT_SIZE; i = i + 1) {
|
||||
c = (i == MC_SHORT_SIZE) ? "" : ",";
|
||||
if (i in shorts) {
|
||||
n = shorts[i];
|
||||
flags = header_flags[n]; if (flags) flags = ",\n " flags;
|
||||
|
||||
printf(" { /* %s */ %s_%s_class, offsetof(%s_t, %s_%s)%s }%s\n",
|
||||
substr(lower_case, i, 1),
|
||||
tprefix, n, module, prefix, n, flags, c) \
|
||||
> PT;
|
||||
}
|
||||
else {
|
||||
printf(" { NULL }%s\n", c) \
|
||||
> PT;
|
||||
}
|
||||
}
|
||||
printf("};\n\n") > PT;
|
||||
}
|
||||
|
||||
# printf("extern msg_hclass_t msg_multipart_class[];\n\n") > PT;
|
||||
|
||||
if (extra > 0) {
|
||||
printf("struct %s {\n", extra_struct) > PT;
|
||||
printf(" %s base;\n", module_struct) > PT;
|
||||
printf(" msg_header_t *extra[%u];\n", extra) > PT;
|
||||
printf("};\n\n") > PT;
|
||||
module_struct = "struct " extra_struct;
|
||||
}
|
||||
|
||||
printf("msg_mclass_t const %s_mclass[1] = \n{{\n", module) > PT;
|
||||
printf("# if defined (%s_HCLASS)\n", toupper(module)) > PT;
|
||||
printf(" %s_HCLASS,\n", toupper(module)) > PT;
|
||||
printf("#else\n") > PT;
|
||||
printf(" {{ 0 }},\n") > PT;
|
||||
printf("#endif\n") > PT;
|
||||
printf(" %s_VERSION_CURRENT,\n", toupper(module)) > PT;
|
||||
printf(" %s_PROTOCOL_TAG,\n", toupper(module)) > PT;
|
||||
printf("#if defined (%s_PARSER_FLAGS)\n", toupper(module)) > PT;
|
||||
printf(" %s_PARSER_FLAGS,\n", toupper(module)) > PT;
|
||||
printf("#else\n") > PT;
|
||||
printf(" 0,\n") > PT;
|
||||
printf("#endif\n") > PT;
|
||||
printf(" sizeof (%s),\n", module_struct) > PT;
|
||||
printf(" %s_extract_body,\n", module) > PT;
|
||||
|
||||
len = split("request status separator payload unknown error", unnamed, " ");
|
||||
|
||||
for (i = 1; i <= len; i++) {
|
||||
printf(" {{ %s_%s_class, offsetof(%s_t, %s_%s) }},\n",
|
||||
tprefix, unnamed[i], module, prefix, unnamed[i]) > PT;
|
||||
}
|
||||
if (multipart) {
|
||||
printf(" {{ %s_class, offsetof(%s_t, %s_multipart) }},\n",
|
||||
multipart, module, prefix) > PT;
|
||||
} else {
|
||||
printf(" {{ NULL, 0 }},\n") > PT;
|
||||
}
|
||||
if (MC_SHORT_SIZE) {
|
||||
printf(" %s_short_forms, \n", module) > PT;
|
||||
}
|
||||
else {
|
||||
printf(" NULL, \n") > PT;
|
||||
}
|
||||
printf(" %d, %d, \n", MC_HASH_SIZE, total) > PT;
|
||||
printf(" {\n") > PT;
|
||||
|
||||
for (i = 0; i < total; i++) {
|
||||
n = headers[i];
|
||||
h = hashed[n];
|
||||
|
||||
if (h < 0)
|
||||
continue;
|
||||
|
||||
j = h % MC_HASH_SIZE; if (j == -0) j = 0;
|
||||
|
||||
for (; j in header_hash;) {
|
||||
if (++j == MC_HASH_SIZE) {
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
|
||||
header_hash[j] = n;
|
||||
}
|
||||
|
||||
for (i = 0; i < MC_HASH_SIZE; i++) {
|
||||
c = (i + 1 == MC_HASH_SIZE) ? "" : ",";
|
||||
if (i in header_hash) {
|
||||
n = header_hash[i];
|
||||
flags = header_flags[n]; if (flags) flags = ",\n " flags;
|
||||
|
||||
if (Since[n]) {
|
||||
printf(" { %s_%s_class, offsetof(struct %s, extra[%u])%s }%s\n",
|
||||
tprefix, n, extra_struct, Extra[n], flags, c) > PT;
|
||||
}
|
||||
else {
|
||||
printf(" { %s_%s_class, offsetof(%s_t, %s_%s)%s }%s\n",
|
||||
tprefix, n, module, prefix, n, flags, c) > PT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf(" { NULL, 0 }%s\n", c) > PT;
|
||||
}
|
||||
}
|
||||
printf(" }\n}};\n\n") > PT;
|
||||
}
|
||||
|
||||
exit success;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,371 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 msg_tag.c Message tag classes
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Fri Feb 23 12:46:42 2001 ppessi
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sofia-sip/su.h>
|
||||
|
||||
#define TAG_NAMESPACE "msg"
|
||||
|
||||
#include "msg_internal.h"
|
||||
#include "sofia-sip/msg_header.h"
|
||||
#include "sofia-sip/msg_parser.h"
|
||||
|
||||
#include <sofia-sip/su_tag_class.h>
|
||||
#include <sofia-sip/su_tag_inline.h>
|
||||
#include <sofia-sip/su_tagarg.h>
|
||||
#include "sofia-sip/msg_tag_class.h"
|
||||
|
||||
#define NONE ((void*)-1)
|
||||
|
||||
int msghdrtag_snprintf(tagi_t const *t, char b[], size_t size)
|
||||
{
|
||||
msg_header_t const *h;
|
||||
|
||||
assert(t);
|
||||
|
||||
if (!t) {
|
||||
if (size) b[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
h = (msg_header_t const *)t->t_value;
|
||||
|
||||
if (h != MSG_HEADER_NONE && h != NULL) {
|
||||
return msg_header_field_e(b, size, h, 0);
|
||||
}
|
||||
else {
|
||||
return snprintf(b, size, "<NONE>");
|
||||
}
|
||||
}
|
||||
|
||||
size_t msghdrtag_xtra(tagi_t const *t, size_t offset)
|
||||
{
|
||||
msg_header_t const *h;
|
||||
size_t rv;
|
||||
msg_hclass_t *hc = (msg_hclass_t *)t->t_tag->tt_magic;
|
||||
assert(t);
|
||||
|
||||
for (h = (msg_header_t const *)t->t_value, rv = offset;
|
||||
h != NULL;
|
||||
h = h->sh_next) {
|
||||
if (h == MSG_HEADER_NONE)
|
||||
break;
|
||||
MSG_STRUCT_SIZE_ALIGN(rv);
|
||||
if (hc)
|
||||
rv = hc->hc_dxtra(h, rv + h->sh_class->hc_size);
|
||||
else
|
||||
rv = h->sh_class->hc_dxtra(h, rv + h->sh_class->hc_size);
|
||||
}
|
||||
|
||||
return rv - offset;
|
||||
}
|
||||
|
||||
tagi_t *msghdrtag_dup(tagi_t *dst, tagi_t const *src, void **bb)
|
||||
{
|
||||
msg_header_t const *o;
|
||||
msg_header_t *h, *h0 = NULL, **hh;
|
||||
msg_hclass_t *hc, *hc0 = (msg_hclass_t *)src->t_tag->tt_magic;
|
||||
char *b;
|
||||
size_t size;
|
||||
|
||||
assert(src); assert(*bb);
|
||||
|
||||
dst->t_tag = src->t_tag;
|
||||
dst->t_value = 0L;
|
||||
|
||||
b = *bb;
|
||||
hh = &h0;
|
||||
|
||||
for (o = (msg_header_t const *)src->t_value;
|
||||
o != NULL;
|
||||
o = o->sh_next) {
|
||||
if (o == MSG_HEADER_NONE) {
|
||||
*hh = (msg_header_t *)o;
|
||||
break;
|
||||
}
|
||||
|
||||
/* XXX assert(msg_hdr_p(o)); */
|
||||
|
||||
MSG_STRUCT_ALIGN(b);
|
||||
h = (msg_header_t *)b;
|
||||
hc = hc0 ? hc0 : o->sh_class;
|
||||
b += hc->hc_size;
|
||||
memset(h, 0, hc->hc_size);
|
||||
h->sh_class = hc;
|
||||
|
||||
size = SIZE_MAX - (uintptr_t)b;
|
||||
if (size > ISSIZE_MAX)
|
||||
size = ISSIZE_MAX;
|
||||
b = hc->hc_dup_one(h, o, b, size);
|
||||
|
||||
if (hc->hc_update)
|
||||
msg_header_update_params(h->sh_common, 0);
|
||||
|
||||
*hh = h; hh = &h->sh_next;
|
||||
|
||||
assert(b != NULL);
|
||||
}
|
||||
*bb = b;
|
||||
|
||||
dst->t_value = (tag_value_t)h0;
|
||||
|
||||
return dst + 1;
|
||||
}
|
||||
|
||||
|
||||
/** Convert a string to a header structure based on to the tag. */
|
||||
int msghdrtag_scan(tag_type_t tt, su_home_t *home,
|
||||
char const *s,
|
||||
tag_value_t *return_value)
|
||||
{
|
||||
msg_hclass_t *hc = (msg_hclass_t *)tt->tt_magic;
|
||||
msg_header_t *h;
|
||||
int retval;
|
||||
|
||||
h = msg_header_make(home, hc, s);
|
||||
|
||||
if (h)
|
||||
*return_value = (tag_value_t)h, retval = 1;
|
||||
else
|
||||
*return_value = (tag_value_t)NULL, retval = -1;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
tagi_t *msgstrtag_filter(tagi_t *dst,
|
||||
tagi_t const f[],
|
||||
tagi_t const *src,
|
||||
void **bb);
|
||||
|
||||
int msgobjtag_snprintf(tagi_t const *t, char b[], size_t size)
|
||||
{
|
||||
msg_pub_t const *mo;
|
||||
|
||||
assert(t);
|
||||
|
||||
if (!t || !t->t_value) {
|
||||
if (size) b[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
mo = (msg_pub_t *)t->t_value;
|
||||
|
||||
return (int)msg_object_e(b, size, mo, MSG_DO_CANONIC);
|
||||
}
|
||||
|
||||
|
||||
size_t msgobjtag_xtra(tagi_t const *t, size_t offset)
|
||||
{
|
||||
msg_header_t const *h;
|
||||
msg_pub_t const *mo;
|
||||
size_t rv;
|
||||
|
||||
assert(t);
|
||||
|
||||
mo = (msg_pub_t const *)t->t_value;
|
||||
|
||||
if (mo == NULL || mo == NONE)
|
||||
return 0;
|
||||
|
||||
rv = offset;
|
||||
|
||||
MSG_STRUCT_SIZE_ALIGN(rv);
|
||||
rv += mo->msg_size;
|
||||
|
||||
if (mo->msg_request)
|
||||
h = (msg_header_t const *)mo->msg_request;
|
||||
else
|
||||
h = (msg_header_t const *)mo->msg_status;
|
||||
|
||||
for (; h; h = h->sh_succ) {
|
||||
MSG_STRUCT_SIZE_ALIGN(rv);
|
||||
rv += msg_header_size(h);
|
||||
}
|
||||
|
||||
return rv - offset;
|
||||
}
|
||||
|
||||
|
||||
tagi_t *msgobjtag_dup(tagi_t *dst, tagi_t const *src, void **bb)
|
||||
{
|
||||
msg_pub_t const *omo;
|
||||
msg_pub_t *mo;
|
||||
msg_header_t *h;
|
||||
msg_header_t const *o;
|
||||
char *b;
|
||||
|
||||
assert(src); assert(*bb);
|
||||
|
||||
omo = (msg_pub_t const *)src->t_value;
|
||||
|
||||
dst->t_tag = src->t_tag;
|
||||
dst->t_value = 0;
|
||||
|
||||
if (omo == NULL || omo == NONE) {
|
||||
dst->t_value = src->t_value;
|
||||
return dst + 1;
|
||||
}
|
||||
|
||||
b = *bb;
|
||||
MSG_STRUCT_ALIGN(b);
|
||||
mo = (msg_pub_t *)b;
|
||||
b += omo->msg_size;
|
||||
|
||||
memset(mo, 0, omo->msg_size);
|
||||
mo->msg_size = omo->msg_size;
|
||||
mo->msg_flags = omo->msg_flags;
|
||||
|
||||
if (mo->msg_request)
|
||||
o = mo->msg_request;
|
||||
else
|
||||
o = mo->msg_status;
|
||||
|
||||
for (; o; o = o->sh_succ) {
|
||||
size_t size;
|
||||
MSG_STRUCT_ALIGN(b);
|
||||
h = (msg_header_t *)b;
|
||||
b += o->sh_class->hc_size;
|
||||
memset(h, 0, o->sh_class->hc_size);
|
||||
h->sh_class = o->sh_class;
|
||||
size = SIZE_MAX - (uintptr_t)b;
|
||||
if (size > ISSIZE_MAX)
|
||||
size = ISSIZE_MAX;
|
||||
b = o->sh_class->hc_dup_one(h, o, b, size);
|
||||
if (o->sh_class->hc_update)
|
||||
msg_header_update_params(h->sh_common, 0);
|
||||
assert(b != NULL);
|
||||
}
|
||||
|
||||
dst->t_value = (tag_value_t)mo;
|
||||
*bb = b;
|
||||
|
||||
return dst + 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
int msgtag_multipart_xtra(tagi_t const *t, int offset)
|
||||
{
|
||||
msg_header_t const *h;
|
||||
msg_multipart_t const *mp;
|
||||
int rv;
|
||||
|
||||
assert(t);
|
||||
|
||||
mp = (msg_multipart_t const *)t->t_value;
|
||||
|
||||
if (mp == NULL || mp == NONE)
|
||||
return 0;
|
||||
|
||||
rv = offset;
|
||||
|
||||
MSG_STRUCT_SIZE_ALIGN(rv);
|
||||
rv += mo->msg_size;
|
||||
|
||||
if (mo->msg_request)
|
||||
h = (msg_header_t const *)mo->msg_request;
|
||||
else
|
||||
h = (msg_header_t const *)mo->msg_status;
|
||||
|
||||
for (; h; h = h->sh_succ) {
|
||||
MSG_STRUCT_SIZE_ALIGN(rv);
|
||||
rv += msg_header_size(h);
|
||||
}
|
||||
|
||||
return rv - offset;
|
||||
}
|
||||
|
||||
|
||||
tagi_t *msgtag_multipart_dup(tagi_t *dst, tagi_t const *src, void **bb)
|
||||
{
|
||||
msg_pub_t const *omo;
|
||||
msg_pub_t *mo;
|
||||
msg_header_t *h;
|
||||
msg_header_t const *o;
|
||||
char *b;
|
||||
|
||||
assert(src); assert(*bb);
|
||||
|
||||
omo = (msg_pub_t const *)src->t_value;
|
||||
|
||||
dst->t_tag = src->t_tag;
|
||||
dst->t_value = 0;
|
||||
|
||||
if (omo == NULL || omo == NONE) {
|
||||
dst->t_value = src->t_value;
|
||||
return dst + 1;
|
||||
}
|
||||
|
||||
b = *bb;
|
||||
MSG_STRUCT_ALIGN(b);
|
||||
mo = (msg_pub_t *)b;
|
||||
b += omo->msg_size;
|
||||
|
||||
memset(mo, 0, omo->msg_size);
|
||||
mo->msg_size = omo->msg_size;
|
||||
mo->msg_flags = omo->msg_flags;
|
||||
|
||||
if (mo->msg_request)
|
||||
o = mo->msg_request;
|
||||
else
|
||||
o = mo->msg_status;
|
||||
|
||||
for (; o; o = o->sh_succ) {
|
||||
size_t size;
|
||||
MSG_STRUCT_ALIGN(b);
|
||||
h = (msg_header_t *)b;
|
||||
b += o->sh_class->hc_size;
|
||||
memset(h, 0, o->sh_class->hc_size);
|
||||
h->sh_class = o->sh_class;
|
||||
size = SIZE_MAX - (uintptr_t)b;
|
||||
if (size > ISSIZE_MAX)
|
||||
size = ISSIZE_MAX;
|
||||
b = o->sh_class->hc_dup_one(h, o, b, size);
|
||||
if (o->sh_class->hc_update)
|
||||
msg_header_update_params(h->sh_common, 0);
|
||||
assert(b != NULL);
|
||||
}
|
||||
|
||||
dst->t_value = (long)mo;
|
||||
*bb = b;
|
||||
|
||||
return dst + 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MSG_H
|
||||
/** Defined when <sofia-sip/msg.h> has been included */
|
||||
#define MSG_H
|
||||
/**@file sofia-sip/msg.h
|
||||
*
|
||||
* Base message interface.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Fri Feb 18 08:54:48 2000 ppessi
|
||||
*/
|
||||
|
||||
#include <sofia-sip/msg_types.h>
|
||||
#include <sofia-sip/su_alloc.h>
|
||||
|
||||
SOFIA_BEGIN_DECLS
|
||||
|
||||
SOFIAPUBFUN msg_t *msg_create(msg_mclass_t const *mc, int flags);
|
||||
SOFIAPUBFUN void msg_destroy(msg_t *);
|
||||
|
||||
SOFIAPUBFUN msg_t *msg_copy(msg_t *);
|
||||
SOFIAPUBFUN msg_t *msg_dup(msg_t const *);
|
||||
|
||||
SOFIAPUBFUN msg_t *msg_make(msg_mclass_t const *mc, int flags,
|
||||
void const *data, ssize_t len);
|
||||
SOFIAPUBFUN char *msg_as_string(su_home_t *home,
|
||||
msg_t *msg, msg_pub_t *pub, int flags,
|
||||
size_t *return_len);
|
||||
|
||||
SOFIAPUBFUN void msg_set_parent(msg_t *kid, msg_t *dad);
|
||||
|
||||
SOFIAPUBFUN msg_t *msg_ref_create(msg_t *);
|
||||
SOFIAPUBFUN void msg_ref_destroy(msg_t *);
|
||||
|
||||
SOFIAPUBFUN msg_pub_t *msg_public(msg_t const *msg, void *tag);
|
||||
SOFIAPUBFUN msg_pub_t *msg_object(msg_t const *msg);
|
||||
SOFIAPUBFUN msg_mclass_t const *msg_mclass(msg_t const *msg);
|
||||
|
||||
SOFIAPUBFUN int msg_extract(msg_t *msg);
|
||||
SOFIAPUBFUN unsigned msg_extract_errors(msg_t const *msg);
|
||||
SOFIAPUBFUN int msg_is_complete(msg_t const *msg);
|
||||
SOFIAPUBFUN int msg_has_error(msg_t const *msg);
|
||||
SOFIAPUBFUN msg_header_t **msg_chain_head(msg_t const *msg);
|
||||
|
||||
SOFIAPUBFUN int msg_serialize(msg_t *msg, msg_pub_t *mo);
|
||||
SOFIAPUBFUN int msg_prepare(msg_t *msg);
|
||||
SOFIAPUBFUN void msg_unprepare(msg_t *msg);
|
||||
SOFIAPUBFUN int msg_is_prepared(msg_t const *msg);
|
||||
|
||||
SOFIAPUBFUN usize_t msg_size(msg_t const *msg);
|
||||
SOFIAPUBFUN usize_t msg_maxsize(msg_t *msg, usize_t maxsize);
|
||||
|
||||
/** Cast a #msg_t pointer to a #su_home_t pointer. */
|
||||
#define msg_home(h) ((su_home_t*)(h))
|
||||
|
||||
/** Streaming state of a #msg_t object. */
|
||||
enum msg_streaming_status {
|
||||
/** Disable streaming */
|
||||
msg_stop_streaming = 0,
|
||||
/** Enable streaming */
|
||||
msg_start_streaming = 1
|
||||
};
|
||||
|
||||
SOFIAPUBFUN int msg_is_streaming(msg_t const *msg);
|
||||
SOFIAPUBFUN void msg_set_streaming(msg_t *msg, enum msg_streaming_status what);
|
||||
|
||||
SOFIAPUBFUN unsigned msg_mark_as_complete(msg_t *msg, unsigned mask);
|
||||
|
||||
SOFIAPUBFUN unsigned msg_get_flags(msg_t const *msg, unsigned mask);
|
||||
SOFIAPUBFUN unsigned msg_set_flags(msg_t *msg, unsigned mask);
|
||||
SOFIAPUBFUN unsigned msg_zap_flags(msg_t *msg, unsigned mask);
|
||||
|
||||
/** Flags controlling parser/printer. */
|
||||
enum msg_flg_user {
|
||||
/** Use compact form when printing. */
|
||||
MSG_FLG_COMPACT = (1<<0),
|
||||
/** Use canonic representation when printing. */
|
||||
MSG_FLG_CANONIC = (1<<1),
|
||||
/** Cache a copy of headers when parsing. */
|
||||
MSG_FLG_EXTRACT_COPY = (1<<2),
|
||||
/** Print comma-separated lists instead of separate headers */
|
||||
MSG_FLG_COMMA_LISTS = (1<<3),
|
||||
|
||||
/**Use mailbox format when parsing - in mailbox format
|
||||
* message has no body unless Content-Length header is present.
|
||||
*/
|
||||
MSG_FLG_MAILBOX = (1<<4),
|
||||
|
||||
/** Use multiple parts for message body */
|
||||
MSG_FLG_CHUNKING = (1<<5),
|
||||
|
||||
/** Enable streaming - parser gives completed message fragments when they
|
||||
* are ready to upper layers */
|
||||
MSG_FLG_STREAMING = (1<<6),
|
||||
|
||||
/** Make messages threadsafe. */
|
||||
MSG_FLG_THRDSAFE = (1<<15),
|
||||
|
||||
MSG_FLG_USERMASK = (1<<16) - 1
|
||||
};
|
||||
|
||||
/** Flags used by parser. */
|
||||
enum msg_flg_parser {
|
||||
/** Extract headers for this message */
|
||||
MSG_FLG_HEADERS = (1<<16),
|
||||
/** Extract body for this message */
|
||||
MSG_FLG_BODY = (1<<17),
|
||||
/** Extract chunks for this message */
|
||||
MSG_FLG_CHUNKS = (1<<18),
|
||||
/** Extract trailers for this message */
|
||||
MSG_FLG_TRAILERS = (1<<19),
|
||||
/** Extract last component of this message */
|
||||
MSG_FLG_FRAGS = (1<<20),
|
||||
/** This message has been completely extracted */
|
||||
MSG_FLG_COMPLETE = (1<<24),
|
||||
|
||||
/** This message has parsing errors */
|
||||
MSG_FLG_ERROR = (1<<25),
|
||||
/** This message is too large */
|
||||
MSG_FLG_TOOLARGE = (1<<26),
|
||||
/** This message is truncated */
|
||||
MSG_FLG_TRUNC = (1<<27),
|
||||
/** This message has timeout */
|
||||
MSG_FLG_TIMEOUT = (1<<28),
|
||||
|
||||
MSG_FLG_PARSERMASK = ((-1) ^ ((1<<16) - 1))
|
||||
};
|
||||
|
||||
#define MSG_DO_COMPACT MSG_FLG_COMPACT
|
||||
#define MSG_DO_CANONIC MSG_FLG_CANONIC
|
||||
#define MSG_DO_EXTRACT_COPY MSG_FLG_EXTRACT_COPY
|
||||
|
||||
/** Test if all the flags in @a v are set in @a f. */
|
||||
#define MSG_FLAGS(f, v) (((f) & (v)) == v)
|
||||
|
||||
#define MSG_IS_COMPACT(f) MSG_FLAGS((f), MSG_FLG_COMPACT)
|
||||
#define MSG_IS_CANONIC(f) MSG_FLAGS((f), MSG_FLG_CANONIC)
|
||||
#define MSG_IS_EXTRACT_COPY(f) MSG_FLAGS((f), MSG_FLG_EXTRACT_COPY)
|
||||
#define MSG_IS_COMMA_LISTS(f) MSG_FLAGS((f), MSG_FLG_COMMA_LISTS)
|
||||
#define MSG_IS_MAILBOX(f) MSG_FLAGS((f), MSG_FLG_MAILBOX)
|
||||
|
||||
#define MSG_HAS_COMPLETE(f) MSG_FLAGS((f), MSG_FLG_COMPLETE)
|
||||
#define MSG_HAS_ERROR(f) MSG_FLAGS((f), MSG_FLG_ERROR)
|
||||
|
||||
#define MSG_IS_COMPLETE(mo) (((mo)->msg_flags & MSG_FLG_COMPLETE) != 0)
|
||||
|
||||
SOFIA_END_DECLS
|
||||
|
||||
#endif /* MSG_H */
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MSG_ADDR_H
|
||||
/** Defined when <sofia-sip/msg_addr.h> has been included. */
|
||||
#define MSG_ADDR_H
|
||||
|
||||
|
||||
/**@file sofia-sip/msg_addr.h
|
||||
* @brief Addressing and I/O interface for messages.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Thu Jun 8 19:28:55 2000 ppessi
|
||||
*/
|
||||
|
||||
#ifndef MSG_H
|
||||
#include <sofia-sip/msg.h>
|
||||
#endif
|
||||
#ifndef SU_H
|
||||
#include <sofia-sip/su.h>
|
||||
#endif
|
||||
|
||||
SOFIA_BEGIN_DECLS
|
||||
|
||||
SOFIAPUBFUN void msg_addr_zero(msg_t *msg);
|
||||
SOFIAPUBFUN su_addrinfo_t *msg_addrinfo(msg_t *msg);
|
||||
|
||||
SOFIAPUBFUN su_sockaddr_t *msg_addr(msg_t *msg);
|
||||
|
||||
SOFIAPUBFUN int msg_get_address(msg_t *msg, su_sockaddr_t *, socklen_t *);
|
||||
SOFIAPUBFUN int msg_set_address(msg_t *msg, su_sockaddr_t const *, socklen_t);
|
||||
|
||||
SOFIAPUBFUN void msg_addr_copy(msg_t *dst, msg_t const *src);
|
||||
|
||||
SOFIAPUBFUN int msg_errno(msg_t const *msg);
|
||||
SOFIAPUBFUN void msg_set_errno(msg_t *msg, int err);
|
||||
|
||||
enum {
|
||||
/** Minimum size of a message buffer */
|
||||
msg_min_size = 512,
|
||||
/** Minimum size of external buffer */
|
||||
msg_min_block = 8192,
|
||||
/** Number of external buffers */
|
||||
msg_n_fragments = 8
|
||||
};
|
||||
|
||||
/** I/O vector type.
|
||||
* @sa msg_recv_iovec(), msg_iovec(), #su_iovec_s, su_vsend(), su_vrecv().
|
||||
*/
|
||||
typedef struct su_iovec_s msg_iovec_t;
|
||||
#define mv_base siv_base
|
||||
#define mv_len siv_len
|
||||
|
||||
SOFIAPUBFUN isize_t msg_iovec(msg_t *msg, msg_iovec_t vec[], isize_t veclen);
|
||||
|
||||
SOFIAPUBFUN issize_t msg_recv_iovec(msg_t *msg,
|
||||
msg_iovec_t vec[], isize_t veclen, usize_t n,
|
||||
int exact);
|
||||
SOFIAPUBFUN isize_t msg_recv_commit(msg_t *msg, usize_t n, int eos);
|
||||
|
||||
SOFIAPUBFUN issize_t msg_recv_buffer(msg_t *msg, void **return_buffer);
|
||||
|
||||
SOFIAPUBFUN msg_t *msg_next(msg_t *msg);
|
||||
|
||||
SOFIAPUBFUN int msg_set_next(msg_t *msg, msg_t *next);
|
||||
|
||||
SOFIAPUBFUN void msg_clear_committed(msg_t *msg);
|
||||
|
||||
SOFIAPUBFUN issize_t msg_buf_external(msg_t *msg,
|
||||
usize_t N,
|
||||
usize_t blocksize);
|
||||
|
||||
SOFIA_END_DECLS
|
||||
|
||||
#endif /* !defined(MSG_ADDR_H) */
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MSG_BUFFER_H
|
||||
/** Defined when <sofia-sip/msg_buffer.h> has been included. */
|
||||
#define MSG_BUFFER_H
|
||||
|
||||
/**@file sofia-sip/msg_buffer.h
|
||||
* @brief Internal buffer management functions.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Fri Nov 8 12:23:00 2002 ppessi
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MSG_TYPES_H
|
||||
#include <sofia-sip/msg_types.h>
|
||||
#endif
|
||||
|
||||
SOFIA_BEGIN_DECLS
|
||||
|
||||
SOFIAPUBFUN void *msg_buf_alloc(msg_t *msg, usize_t size);
|
||||
SOFIAPUBFUN void *msg_buf_exact(msg_t *msg, usize_t size);
|
||||
SOFIAPUBFUN usize_t msg_buf_commit(msg_t *msg, usize_t size, int eos);
|
||||
SOFIAPUBFUN usize_t msg_buf_committed(msg_t const *msg);
|
||||
SOFIAPUBFUN void *msg_buf_committed_data(msg_t const *msg);
|
||||
SOFIAPUBFUN usize_t msg_buf_size(msg_t const *msg);
|
||||
|
||||
SOFIAPUBFUN void *msg_buf_move(msg_t *dst, msg_t const *src);
|
||||
|
||||
SOFIAPUBFUN void msg_buf_set(msg_t *msg, void *b, usize_t size);
|
||||
|
||||
SOFIA_END_DECLS
|
||||
|
||||
#endif /* !defined MSG_BUFFER_H */
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MSG_DATE_H
|
||||
/** Defined when <sofia-sip/msg_date.h> has been included. */
|
||||
#define MSG_DATE_H
|
||||
|
||||
/**@ingroup msg_parser
|
||||
* @file sofia-sip/msg_date.h
|
||||
* @brief Types and functions for handling dates and times.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Thu Jun 8 19:28:55 2000 ppessi
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SU_TYPES_H
|
||||
#include <sofia-sip/su_types.h>
|
||||
#endif
|
||||
|
||||
SOFIA_BEGIN_DECLS
|
||||
|
||||
#ifndef MSG_TIME_T_DEFINED
|
||||
#define MSG_TIME_T_DEFINED
|
||||
/** Time in seconds since epoch (1900-Jan-01 00:00:00). */
|
||||
typedef unsigned long msg_time_t;
|
||||
#endif
|
||||
|
||||
#ifndef MSG_TIME_MAX
|
||||
/** Latest time that can be expressed with msg_time_t. @HIDE */
|
||||
#define MSG_TIME_MAX ((msg_time_t)ULONG_MAX)
|
||||
#endif
|
||||
|
||||
/* Current time. */
|
||||
SOFIAPUBFUN msg_time_t msg_now(void);
|
||||
|
||||
SOFIAPUBFUN issize_t msg_date_delta_d(char const **inout_string,
|
||||
msg_time_t *return_date,
|
||||
msg_time_t *return_delta);
|
||||
|
||||
SOFIAPUBFUN issize_t msg_delta_d(char const **ss, msg_time_t *return_delta);
|
||||
SOFIAPUBFUN issize_t msg_delta_e(char b[], isize_t bsiz, msg_time_t delta);
|
||||
|
||||
/** Decode RFC1123-date, RFC822-date or asctime-date. */
|
||||
SOFIAPUBFUN issize_t msg_date_d(char const **ss, msg_time_t *date);
|
||||
|
||||
/** Encode RFC1123-date. */
|
||||
SOFIAPUBFUN issize_t msg_date_e(char b[], isize_t bsiz, msg_time_t date);
|
||||
|
||||
enum { msg_date_string_size = 29 };
|
||||
|
||||
SOFIA_END_DECLS
|
||||
|
||||
#endif /* !defined(MSG_DATE_H) */
|
||||
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MSG_HEADER_H
|
||||
/** Defined when <sofia-sip/msg_header.h> has been included. */
|
||||
#define MSG_HEADER_H
|
||||
/**@ingroup msg_headers
|
||||
* @file sofia-sip/msg_header.h
|
||||
*
|
||||
* @brief Message headers.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Mon Aug 27 15:44:27 2001 ppessi
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef SU_TYPES_H
|
||||
#include <sofia-sip/su_types.h>
|
||||
#endif
|
||||
#ifndef SU_ALLOC_H
|
||||
#include <sofia-sip/su_alloc.h>
|
||||
#endif
|
||||
#ifndef MSG_H
|
||||
#include <sofia-sip/msg.h>
|
||||
#endif
|
||||
#ifndef URL_H
|
||||
#include <sofia-sip/url.h>
|
||||
#endif
|
||||
|
||||
SOFIA_BEGIN_DECLS
|
||||
|
||||
SOFIAPUBFUN msg_header_t *msg_header_alloc(su_home_t *,
|
||||
msg_hclass_t *hc,
|
||||
isize_t extra)
|
||||
__attribute__((__malloc__));
|
||||
|
||||
SOFIAPUBFUN isize_t msg_header_size(msg_header_t const *h);
|
||||
|
||||
SOFIAPUBFUN msg_header_t **msg_header_offset(msg_t const *,
|
||||
msg_pub_t const *,
|
||||
msg_header_t const *);
|
||||
SOFIAPUBFUN msg_header_t **msg_hclass_offset(msg_mclass_t const *,
|
||||
msg_pub_t const *,
|
||||
msg_hclass_t *);
|
||||
SOFIAPUBFUN msg_header_t *msg_header_access(msg_pub_t const *pub,
|
||||
msg_hclass_t *hc);
|
||||
|
||||
SOFIAPUBFUN msg_header_t *msg_header_copy_as(su_home_t *home,
|
||||
msg_hclass_t *hc,
|
||||
msg_header_t const *o)
|
||||
__attribute__((__malloc__));
|
||||
SOFIAPUBFUN msg_header_t *msg_header_copy(su_home_t *home,
|
||||
msg_header_t const *o)
|
||||
__attribute__((__malloc__));
|
||||
SOFIAPUBFUN msg_header_t *msg_header_copy_one(su_home_t *home,
|
||||
msg_header_t const *o)
|
||||
__attribute__((__malloc__));
|
||||
SOFIAPUBFUN msg_header_t *msg_header_dup_as(su_home_t *home,
|
||||
msg_hclass_t *hc,
|
||||
msg_header_t const *o)
|
||||
__attribute__((__malloc__));
|
||||
SOFIAPUBFUN msg_header_t *msg_header_dup(su_home_t *home,
|
||||
msg_header_t const *h)
|
||||
__attribute__((__malloc__));
|
||||
SOFIAPUBFUN msg_header_t *msg_header_dup_one(su_home_t *home,
|
||||
msg_header_t const *h)
|
||||
__attribute__((__malloc__));
|
||||
|
||||
SOFIAPUBFUN msg_header_t *msg_header_d(su_home_t *home,
|
||||
msg_t const *msg,
|
||||
char const *b);
|
||||
SOFIAPUBFUN issize_t msg_header_e(char b[], isize_t bsiz,
|
||||
msg_header_t const *h,
|
||||
int flags);
|
||||
SOFIAPUBFUN issize_t msg_object_e(char b[], isize_t size,
|
||||
msg_pub_t const *mo,
|
||||
int flags);
|
||||
|
||||
SOFIAPUBFUN issize_t msg_header_field_e(char b[], isize_t bsiz,
|
||||
msg_header_t const *h,
|
||||
int flags);
|
||||
|
||||
SOFIAPUBFUN int msg_header_remove(msg_t *msg,
|
||||
msg_pub_t *mo,
|
||||
msg_header_t *h);
|
||||
|
||||
SOFIAPUBFUN int msg_header_remove_all(msg_t *msg,
|
||||
msg_pub_t *mo,
|
||||
msg_header_t *h);
|
||||
|
||||
SOFIAPUBFUN int msg_header_insert(msg_t *msg, msg_pub_t *mo,
|
||||
msg_header_t *h);
|
||||
|
||||
SOFIAPUBFUN int msg_header_replace(msg_t *msg, msg_pub_t *mo,
|
||||
msg_header_t *old_header,
|
||||
msg_header_t *new_header);
|
||||
|
||||
SOFIAPUBFUN int msg_header_add_dup(msg_t *msg,
|
||||
msg_pub_t *pub,
|
||||
msg_header_t const *o);
|
||||
|
||||
SOFIAPUBFUN int msg_header_add_str(msg_t *msg,
|
||||
msg_pub_t *pub,
|
||||
char const *str);
|
||||
|
||||
SOFIAPUBFUN int msg_header_parse_str(msg_t *msg,
|
||||
msg_pub_t *pub,
|
||||
char *s);
|
||||
|
||||
SOFIAPUBFUN int msg_header_add_dup_as(msg_t *msg,
|
||||
msg_pub_t *pub,
|
||||
msg_hclass_t *hc,
|
||||
msg_header_t const *o);
|
||||
|
||||
SOFIAPUBFUN int msg_header_add_make(msg_t *msg,
|
||||
msg_pub_t *pub,
|
||||
msg_hclass_t *hc,
|
||||
char const *s);
|
||||
|
||||
SOFIAPUBFUN int msg_header_prepend(msg_t *msg,
|
||||
msg_pub_t *pub,
|
||||
msg_header_t **hh,
|
||||
msg_header_t *h);
|
||||
|
||||
SOFIAPUBFUN msg_header_t *msg_header_make(su_home_t *home,
|
||||
msg_hclass_t *hc,
|
||||
char const *s)
|
||||
__attribute__((__malloc__));
|
||||
|
||||
SOFIAPUBFUN msg_header_t *msg_header_format(su_home_t *home,
|
||||
msg_hclass_t *hc,
|
||||
char const *fmt, ...)
|
||||
__attribute__ ((__malloc__, __format__ (printf, 3, 4)));
|
||||
|
||||
SOFIAPUBFUN msg_header_t *msg_header_vformat(su_home_t *home,
|
||||
msg_hclass_t *hc,
|
||||
char const *fmt,
|
||||
va_list ap)
|
||||
__attribute__((__malloc__));
|
||||
|
||||
|
||||
SOFIAPUBFUN void msg_header_free(su_home_t *home,
|
||||
msg_header_t *h);
|
||||
|
||||
SOFIAPUBFUN void msg_header_free_all(su_home_t *home,
|
||||
msg_header_t *h);
|
||||
|
||||
SOFIAPUBFUN msg_payload_t *msg_payload_create(su_home_t *home,
|
||||
void const *data,
|
||||
usize_t len)
|
||||
__attribute__((__malloc__));
|
||||
|
||||
SOFIAPUBFUN msg_separator_t *msg_separator_create(su_home_t *home)
|
||||
__attribute__((__malloc__));
|
||||
|
||||
/* Chunk handling macros */
|
||||
|
||||
/** Get pointer to beginning of available buffer space */
|
||||
#define MSG_CHUNK_BUFFER(pl) \
|
||||
((char *)pl->pl_common->h_data + (pl)->pl_common->h_len)
|
||||
/** Get size of available buffer space */
|
||||
#define MSG_CHUNK_AVAIL(pl) \
|
||||
((pl)->pl_len + ((pl)->pl_data - (char *)pl->pl_common->h_data) - \
|
||||
(pl)->pl_common->h_len)
|
||||
/** Get next chunk in list */
|
||||
#define MSG_CHUNK_NEXT(pl) \
|
||||
((pl)->pl_next)
|
||||
|
||||
SOFIAPUBFUN issize_t msg_headers_prepare(msg_t *,
|
||||
msg_header_t *headers,
|
||||
int flags);
|
||||
|
||||
#ifdef SU_HAVE_INLINE
|
||||
/** Clear encoded data from header structure. */
|
||||
static inline void msg_fragment_clear(msg_common_t *h)
|
||||
{
|
||||
h->h_data = NULL, h->h_len = 0;
|
||||
}
|
||||
|
||||
/** Pointer to header parameters. */
|
||||
static inline
|
||||
msg_param_t **msg_header_params(msg_common_t const *h)
|
||||
{
|
||||
if (h && h->h_class->hc_params) {
|
||||
return (msg_param_t **)((char *)h + h->h_class->hc_params);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
#define msg_fragment_clear(h) ((h)->h_data = NULL, (h)->h_len = 0)
|
||||
#define msg_header_params(h) \
|
||||
(((h) && ((msg_common_t *)h)->h_class->hc_params) ? \
|
||||
(msg_param_t **)((char *)(h) + ((msg_common_t *)h)->h_class->hc_params) : NULL)
|
||||
#endif
|
||||
|
||||
SOFIAPUBFUN char const *msg_header_find_param(msg_common_t const *,
|
||||
char const *name);
|
||||
SOFIAPUBFUN int msg_header_add_param(su_home_t *, msg_common_t *h,
|
||||
char const *param);
|
||||
SOFIAPUBFUN int msg_header_replace_param(su_home_t *, msg_common_t *h,
|
||||
char const *param);
|
||||
SOFIAPUBFUN int msg_header_remove_param(msg_common_t *h, char const *name);
|
||||
|
||||
SOFIAPUBFUN char const *msg_header_find_item(msg_common_t const *h,
|
||||
char const *item);
|
||||
|
||||
SOFIAPUBFUN int msg_header_replace_item(su_home_t *, msg_common_t *h,
|
||||
char const *item);
|
||||
SOFIAPUBFUN int msg_header_remove_item(msg_common_t *h, char const *name);
|
||||
|
||||
/** Append a list of constant items to a list. */
|
||||
SOFIAPUBFUN int msg_list_append_items(su_home_t *home,
|
||||
msg_list_t *k,
|
||||
msg_param_t const items[]);
|
||||
|
||||
/** Replace a list of constant items on a list */
|
||||
SOFIAPUBFUN int msg_list_replace_items(su_home_t *home,
|
||||
msg_list_t *k,
|
||||
msg_param_t const items[]);
|
||||
|
||||
SOFIAPUBFUN int msg_header_join_items(su_home_t *home,
|
||||
msg_common_t *dst,
|
||||
msg_common_t const *src,
|
||||
int duplicate);
|
||||
|
||||
SOFIAPUBFUN issize_t msg_random_token(char token[], isize_t tlen,
|
||||
void const *d, isize_t dlen);
|
||||
|
||||
SOFIAPUBFUN msg_param_t msg_params_find(msg_param_t const pp[],
|
||||
char const *name);
|
||||
SOFIAPUBFUN msg_param_t *msg_params_find_slot(msg_param_t [],
|
||||
char const *name);
|
||||
SOFIAPUBFUN int msg_params_add(su_home_t *sh,
|
||||
msg_param_t **pp,
|
||||
char const *param);
|
||||
SOFIAPUBFUN int msg_params_cmp(char const * const a[],
|
||||
char const * const b[]);
|
||||
SOFIAPUBFUN int msg_params_replace(su_home_t *,
|
||||
char const * **inout_paramlist,
|
||||
char const *);
|
||||
SOFIAPUBFUN int msg_params_remove(char const **paramlist,
|
||||
char const *name);
|
||||
SOFIAPUBFUN size_t msg_params_length(char const * const * params);
|
||||
|
||||
/** Unquote a string, return a duplicate. */
|
||||
SOFIAPUBFUN char *msg_unquote_dup(su_home_t *home, char const *q)
|
||||
__attribute__((__malloc__));
|
||||
|
||||
SOFIAPUBFUN char *msg_unquote(char *dst, char const *s);
|
||||
|
||||
/** Calculate a hash over a string. */
|
||||
SOFIAPUBFUN unsigned long msg_hash_string(char const *id);
|
||||
|
||||
/* Align pointer p for multiple of t (which must be a power of 2) */
|
||||
#define MSG_ALIGN(p, t) (((uintptr_t)(p) + (t) - 1) & (0 - (uintptr_t)(t)))
|
||||
#define MSG_STRUCT_SIZE_ALIGN(rv) ((rv) = MSG_ALIGN(rv, sizeof(void *)))
|
||||
#define MSG_STRUCT_ALIGN(p) ((p) = (void*)MSG_ALIGN(p, sizeof(void *)))
|
||||
|
||||
enum {
|
||||
msg_n_params = 8, /* allocation size of parameter string list */
|
||||
#define MSG_N_PARAMS msg_n_params
|
||||
};
|
||||
|
||||
/** Initialize a header structure. @HIDE */
|
||||
#define MSG_HEADER_INIT(h, msg_class, size) \
|
||||
((void)memset((h), 0, (size)), \
|
||||
(void)(((msg_common_t *)(h))->h_class = (msg_class)), \
|
||||
(h))
|
||||
|
||||
/** No header. */
|
||||
#define MSG_HEADER_NONE ((msg_header_t *)-1)
|
||||
|
||||
SOFIA_END_DECLS
|
||||
|
||||
#ifndef MSG_PROTOS_H
|
||||
#include <sofia-sip/msg_protos.h>
|
||||
#endif
|
||||
|
||||
#endif /** !defined(MSG_HEADER_H) */
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MSG_MCLASS_H
|
||||
/** Defined when <sofia-sip/msg_mclass.h> has been included. */
|
||||
#define MSG_MCLASS_H
|
||||
/**@ingroup msg_parser
|
||||
* @file sofia-sip/msg_mclass.h
|
||||
*
|
||||
* @brief Parser table and message factory object.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Mon Aug 27 15:44:27 2001 ppessi
|
||||
*/
|
||||
|
||||
#ifndef MSG_HEADER_H
|
||||
#include <sofia-sip/msg_header.h>
|
||||
#endif
|
||||
|
||||
SOFIA_BEGIN_DECLS
|
||||
|
||||
enum {
|
||||
/** Default size of hash table */
|
||||
MC_HASH_SIZE = 127,
|
||||
/** Size of short form table */
|
||||
MC_SHORT_SIZE = 'Z' - 'A' + 1
|
||||
};
|
||||
|
||||
/**Header reference.
|
||||
*
|
||||
* A header reference object contains a pointer to a
|
||||
* @ref msg_hclass_s "header class"
|
||||
* and a offset to the header objects within the @ref msg_pub_t "public
|
||||
* message structure".
|
||||
*
|
||||
* The @a hr_flags field is used to provide classification of headers. For
|
||||
* instance, the msg_extract_errors() returns bitwise or of all hr_flags
|
||||
* belonging to headers with parsing errors.
|
||||
*/
|
||||
struct msg_href_s
|
||||
{
|
||||
msg_hclass_t *hr_class; /**< Header class */
|
||||
unsigned short hr_offset; /**< Offset within public message struct. */
|
||||
unsigned short hr_flags; /**< Header flags */
|
||||
};
|
||||
|
||||
/**Factory object for protocol messages.
|
||||
*
|
||||
* The message class is a kind of a factory object used to create new
|
||||
* message objects for the protocol it represents (see msg_create()).
|
||||
*
|
||||
* The message class object contains all the information needed to parse a
|
||||
* message. It used when headers are added or removed from the message. When
|
||||
* a message is sent, the message class is used to order message components
|
||||
* and print (encode) the message in text format.
|
||||
*
|
||||
* The message class contains reference objects to headers and other components
|
||||
* within the message. Each reference contains a pointer to a @ref
|
||||
* msg_hclass_s "header class" and a offset to the header objects within
|
||||
* public message structure. The parser engine uses these references when it
|
||||
* adds a newly parsed header object to the message structure. The function
|
||||
* msg_find_hclass() searches for the reference of the named header.
|
||||
|
||||
* The application can make a copy of existing message class object using
|
||||
* the function msg_mclass_clone(). New headers can be added to the message
|
||||
* class with the msg_mclass_insert_header() and msg_mclass_insert()
|
||||
* functions. The message class of an existing message object can be found
|
||||
* out with the function msg_mclass().
|
||||
*
|
||||
* @sa sip_default_mclass(), http_default_mclass(), msg_create(),
|
||||
* msg_mclass(), msg_mclass_clone(), msg_mclass_insert_header(),
|
||||
* msg_mclass_insert_with_mask(), msg_mclass_insert().
|
||||
*/
|
||||
struct msg_mclass_s
|
||||
{
|
||||
struct msg_hclass_s
|
||||
mc_hclass[1]; /**< Recursive header class */
|
||||
char const *mc_name; /**< Protocol name, e.g., "SIP/2.0" */
|
||||
void *mc_tag; /**< Protocol-specific tag */
|
||||
unsigned mc_flags; /**< Default flags */
|
||||
unsigned mc_msize; /**< Size of public message structure */
|
||||
/** Function extracting the message contents. */
|
||||
issize_t (*mc_extract_body)(msg_t *msg, msg_pub_t *pub,
|
||||
char b[], isize_t bsiz, int eos);
|
||||
|
||||
msg_href_t mc_request[1]; /**< Request line reference */
|
||||
msg_href_t mc_status[1]; /**< Status line reference */
|
||||
msg_href_t mc_separator[1];/**< Separator line reference */
|
||||
msg_href_t mc_payload[1]; /**< Message body reference */
|
||||
msg_href_t mc_unknown[1]; /**< Reference for unknown headers */
|
||||
msg_href_t mc_error[1]; /**< Reference for erroneous header */
|
||||
msg_href_t mc_multipart[1];/**< Multipart body reference */
|
||||
msg_href_t const *
|
||||
mc_short; /**< Short forms (or NULL) */
|
||||
short mc_hash_size; /**< Size of parsing table */
|
||||
short mc_hash_used; /**< Number of headers in parsing table */
|
||||
/** Hash table for parsing containing reference for each header. */
|
||||
msg_href_t mc_hash[MC_HASH_SIZE];
|
||||
};
|
||||
|
||||
enum { msg_mclass_copy = 0, msg_mclass_empty = 1 };
|
||||
|
||||
SOFIAPUBFUN msg_mclass_t *msg_mclass_clone(msg_mclass_t const *old,
|
||||
int newsize, int empty);
|
||||
|
||||
SOFIAPUBFUN int msg_mclass_insert(msg_mclass_t *mc, msg_href_t const *hr);
|
||||
|
||||
SOFIAPUBFUN
|
||||
int msg_mclass_insert_header(msg_mclass_t *mc,
|
||||
msg_hclass_t *hc,
|
||||
unsigned short offset);
|
||||
|
||||
SOFIAPUBFUN
|
||||
int msg_mclass_insert_with_mask(msg_mclass_t *mc,
|
||||
msg_hclass_t *hc,
|
||||
unsigned short offset,
|
||||
unsigned short mask);
|
||||
|
||||
SOFIAPUBFUN
|
||||
msg_href_t const *msg_find_hclass(msg_mclass_t const *, char const *, isize_t *);
|
||||
|
||||
SOFIAPUBFUN msg_mclass_t const *msg_mclass(msg_t const *);
|
||||
|
||||
SOFIA_END_DECLS
|
||||
|
||||
#endif /* !defined(MSG_MCLASS_H) */
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MSG_MCLASS_HASH_H
|
||||
/** Defined when <sofia-sip/msg_mclass_hash.h> has been included. */
|
||||
#define MSG_MCLASS_HASH_H
|
||||
|
||||
/**@ingroup msg_parser
|
||||
* @file sofia-sip/msg_mclass_hash.h
|
||||
*
|
||||
* Hash function for header names.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Tue Aug 21 16:03:45 2001 ppessi
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sofia-sip/su_config.h>
|
||||
|
||||
#ifndef BNF_H
|
||||
#include <sofia-sip/bnf.h>
|
||||
#endif
|
||||
|
||||
SOFIA_BEGIN_DECLS
|
||||
|
||||
/** Hash the header name */
|
||||
#define MC_HASH(s, n) (msg_header_name_hash(s, NULL) % (unsigned)(n))
|
||||
|
||||
/** Hash header name */
|
||||
static inline
|
||||
unsigned short msg_header_name_hash(char const *s, isize_t *llen)
|
||||
{
|
||||
unsigned short hash = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; s[i]; i++) {
|
||||
unsigned char c = s[i];
|
||||
if (!(_bnf_table[c] & bnf_token))
|
||||
break;
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
hash += (c + 'a' - 'A');
|
||||
else
|
||||
hash += c;
|
||||
hash *= 38501U;
|
||||
}
|
||||
|
||||
if (llen)
|
||||
*llen = i;
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
SOFIA_END_DECLS
|
||||
|
||||
#endif /** MSG_MCLASS_HASH_H */
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MSG_MIME_H
|
||||
/** Defined when <sofia-sip/msg_mime.h> has been included. */
|
||||
#define MSG_MIME_H
|
||||
|
||||
/**@ingroup msg_mime
|
||||
* @file sofia-sip/msg_mime.h
|
||||
*
|
||||
* MIME headers and multipart messages (@RFC2045).
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Fri Aug 16 19:18:26 EEST 2002 ppessi
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef URL_H
|
||||
#include <sofia-sip/url.h>
|
||||
#endif
|
||||
|
||||
#ifndef MSG_TYPES_H
|
||||
#include <sofia-sip/msg_types.h>
|
||||
#endif
|
||||
#ifndef SU_TYPES_H
|
||||
#include <sofia-sip/su_types.h>
|
||||
#endif
|
||||
|
||||
SOFIA_BEGIN_DECLS
|
||||
|
||||
typedef struct msg_accept_any_s msg_accept_any_t;
|
||||
|
||||
typedef struct msg_accept_s msg_accept_t;
|
||||
|
||||
typedef msg_accept_any_t msg_accept_charset_t;
|
||||
typedef msg_accept_any_t msg_accept_encoding_t;
|
||||
typedef msg_accept_any_t msg_accept_language_t;
|
||||
|
||||
typedef struct msg_content_disposition_s
|
||||
msg_content_disposition_t;
|
||||
typedef msg_list_t msg_content_encoding_t;
|
||||
typedef msg_generic_t msg_content_id_t;
|
||||
typedef struct msg_content_length_s msg_content_length_t;
|
||||
typedef msg_generic_t msg_content_location_t;
|
||||
typedef msg_list_t msg_content_language_t;
|
||||
typedef msg_generic_t msg_content_md5_t;
|
||||
typedef msg_generic_t msg_content_transfer_encoding_t;
|
||||
typedef struct msg_content_type_s msg_content_type_t;
|
||||
typedef msg_generic_t msg_mime_version_t;
|
||||
typedef struct msg_warning_s msg_warning_t;
|
||||
|
||||
/** Multipart body object. */
|
||||
typedef struct msg_multipart_s msg_multipart_t;
|
||||
|
||||
/**@ingroup msg_accept
|
||||
* @brief Structure for @b Accept header.
|
||||
*/
|
||||
struct msg_accept_s
|
||||
{
|
||||
msg_common_t ac_common[1]; /**< Common fragment info */
|
||||
msg_accept_t *ac_next; /**< Pointer to next Accept header */
|
||||
char const *ac_type; /**< Pointer to type/subtype */
|
||||
char const *ac_subtype; /**< Points after first slash in type */
|
||||
msg_param_t const *ac_params; /**< List of parameters */
|
||||
char const *ac_q; /**< Value of q parameter */
|
||||
};
|
||||
|
||||
/**@ingroup msg_accept_encoding
|
||||
* @brief Structure for @b Accept-Charset, @b Accept-Encoding and
|
||||
* @b Accept-Language headers.
|
||||
*/
|
||||
struct msg_accept_any_s
|
||||
{
|
||||
msg_common_t aa_common[1]; /**< Common fragment info */
|
||||
msg_accept_any_t *aa_next; /**< Pointer to next Accept-* header */
|
||||
char const *aa_value; /**< Token */
|
||||
msg_param_t const *aa_params; /**< List of parameters */
|
||||
char const *aa_q; /**< Value of q parameter */
|
||||
};
|
||||
|
||||
/**@ingroup msg_content_disposition
|
||||
* @brief Structure for @b Content-Disposition header.
|
||||
*/
|
||||
struct msg_content_disposition_s
|
||||
{
|
||||
msg_common_t cd_common[1]; /**< Common fragment info */
|
||||
msg_error_t *cd_next; /**< Link to next (dummy) */
|
||||
char const *cd_type; /**< Disposition type */
|
||||
msg_param_t const *cd_params; /**< List of parameters */
|
||||
char const *cd_handling; /**< Value of @b handling parameter */
|
||||
unsigned cd_required:1; /**< True if handling=required */
|
||||
unsigned cd_optional:1; /**< True if handling=optional */
|
||||
unsigned :0; /* pad */
|
||||
};
|
||||
|
||||
/**@ingroup msg_content_length
|
||||
* @brief Structure for Content-Length header.
|
||||
*/
|
||||
struct msg_content_length_s
|
||||
{
|
||||
msg_common_t l_common[1]; /**< Common fragment info */
|
||||
msg_error_t *l_next; /**< Link to next (dummy) */
|
||||
unsigned long l_length; /**< Digits */
|
||||
};
|
||||
|
||||
|
||||
/**@ingroup msg_content_type
|
||||
* @brief Structure for Content-Type header.
|
||||
*/
|
||||
struct msg_content_type_s
|
||||
{
|
||||
msg_common_t c_common[1]; /**< Common fragment info */
|
||||
msg_error_t *c_next; /**< Dummy link to next */
|
||||
char const *c_type; /**< Pointer to type/subtype */
|
||||
char const *c_subtype; /**< Points after first slash in type */
|
||||
msg_param_t const *c_params; /**< List of parameters */
|
||||
};
|
||||
|
||||
|
||||
/**@ingroup sip_warning
|
||||
* @brief Structure for @b Warning header.
|
||||
*/
|
||||
struct msg_warning_s
|
||||
{
|
||||
msg_common_t w_common[1]; /**< Common fragment info */
|
||||
msg_warning_t *w_next; /**< Link to next Warning header */
|
||||
unsigned w_code; /**< Warning code */
|
||||
char const *w_host; /**< Hostname or pseudonym */
|
||||
char const *w_port; /**< Port number */
|
||||
char const *w_text; /**< Warning text */
|
||||
};
|
||||
|
||||
|
||||
/**@ingroup msg_multipart
|
||||
*
|
||||
* @brief Structure for a part in MIME multipart message.
|
||||
*/
|
||||
struct msg_multipart_s
|
||||
{
|
||||
msg_common_t mp_common[1]; /**< Common fragment information */
|
||||
msg_multipart_t *mp_next; /**< Next part in multipart body */
|
||||
/* Preamble for this part */
|
||||
char *mp_data; /**< Boundary string. */
|
||||
usize_t mp_len; /**< Length of boundary (mp_data).*/
|
||||
unsigned mp_flags;
|
||||
msg_error_t *mp_error;
|
||||
|
||||
/* === Headers start here */
|
||||
msg_content_type_t *mp_content_type; /**< Content-Type */
|
||||
msg_content_disposition_t *mp_content_disposition;
|
||||
/**< Content-Disposition */
|
||||
msg_content_location_t *mp_content_location; /**< Content-Location */
|
||||
msg_content_id_t *mp_content_id; /**< Content-ID */
|
||||
msg_content_language_t *mp_content_language; /**< Content-Language */
|
||||
msg_content_encoding_t *mp_content_encoding; /**< Content-Encoding */
|
||||
msg_content_transfer_encoding_t *mp_content_transfer_encoding;
|
||||
/**< Content-Transfer-Encoding */
|
||||
#if 0
|
||||
/* === Hash headers end here */
|
||||
/* These MIME headers are here for msg_parser.awk */
|
||||
msg_accept_t *mp_accept; /**< Accept */
|
||||
msg_accept_charset_t *mp_accept_charset; /**< Accept-Charset */
|
||||
msg_accept_encoding_t *mp_accept_encoding; /**< Accept-Encoding */
|
||||
msg_accept_language_t *mp_accept_language; /**< Accept-Language */
|
||||
msg_mime_version_t *mp_mime_version; /**< MIME-Version */
|
||||
msg_content_md5_t *mp_content_md5; /**< Content-MD5 */
|
||||
msg_content_length_t *mp_content_length; /**< Content-Length */
|
||||
msg_multipart_t *mp_multipart; /**< Recursive multipart */
|
||||
msg_warning_t *mp_warning; /**< Warning */
|
||||
#endif
|
||||
/* === Headers end here */
|
||||
|
||||
/** Unknown and extra headers. */
|
||||
msg_unknown_t *mp_unknown; /**< Unknown headers */
|
||||
|
||||
msg_separator_t *mp_separator; /**< Separator */
|
||||
msg_payload_t *mp_payload; /**< Body part */
|
||||
|
||||
msg_multipart_t *mp_multipart; /**< Recursive multipart */
|
||||
|
||||
msg_payload_t *mp_close_delim; /**< Closing delimiter */
|
||||
};
|
||||
|
||||
SOFIAPUBFUN
|
||||
msg_multipart_t *msg_multipart_create(su_home_t *home,
|
||||
char const *content_type,
|
||||
void const *data,
|
||||
isize_t dlen);
|
||||
SOFIAPUBFUN
|
||||
msg_multipart_t *msg_multipart_parse(su_home_t *home,
|
||||
msg_content_type_t const *c,
|
||||
msg_payload_t *pl);
|
||||
SOFIAPUBFUN
|
||||
int msg_multipart_complete(su_home_t *home,
|
||||
msg_content_type_t *c,
|
||||
msg_multipart_t *mp);
|
||||
SOFIAPUBFUN msg_header_t *msg_multipart_serialize(msg_header_t **head0,
|
||||
msg_multipart_t *mp);
|
||||
|
||||
SOFIAPUBFUN issize_t msg_multipart_prepare(msg_t *msg, msg_multipart_t *mp, int flags);
|
||||
|
||||
SOFIAPUBFUN isize_t msg_accept_any_dup_xtra(msg_header_t const *h, isize_t offset);
|
||||
|
||||
SOFIAPUBFUN char *msg_accept_any_dup_one(msg_header_t *dst,
|
||||
msg_header_t const *src,
|
||||
char *b, isize_t xtra);
|
||||
|
||||
SOFIAPUBFUN
|
||||
msg_content_length_t *msg_content_length_create(su_home_t *home, uint32_t n);
|
||||
|
||||
/** MIME multipart protocol name. @HIDE */
|
||||
#define MSG_MULTIPART_VERSION_CURRENT msg_mime_version_1_0
|
||||
SOFIAPUBVAR char const msg_mime_version_1_0[];
|
||||
|
||||
/** MIME multipart parser table identifier. @HIDE */
|
||||
#define MSG_MULTIPART_PROTOCOL_TAG ((void *)0x4d494d45) /* 'MIME' */
|
||||
|
||||
SOFIA_END_DECLS
|
||||
|
||||
#endif /** MSG_MIME_H */
|
||||
@@ -0,0 +1,323 @@
|
||||
/**@ingroup msg -*- c -*-
|
||||
* @file sofia-sip/msg_mime_protos.h.in
|
||||
*
|
||||
* Template for <msg_mime_protos.h>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MSG_MIME_PROTOS_H
|
||||
/** Defined when <sofia-sip/msg_mime_protos.h> has been included. */
|
||||
#define MSG_MIME_PROTOS_H
|
||||
|
||||
/**@ingroup msg_mime
|
||||
* @file sofia-sip/msg_mime_protos.h
|
||||
*
|
||||
* Prototypes for MIME headers (@RFC2045).
|
||||
*
|
||||
* #AUTO#
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*/
|
||||
|
||||
#ifndef MSG_PARSER_H
|
||||
#include <sofia-sip/msg_parser.h>
|
||||
#endif
|
||||
#ifndef MSG_MIME_H
|
||||
#include <sofia-sip/msg_mime.h>
|
||||
#endif
|
||||
#ifndef MSG_MCLASS_H
|
||||
#include <sofia-sip/msg_mclass.h>
|
||||
#endif
|
||||
#ifndef MSG_MCLASS_H
|
||||
#include <sofia-sip/msg_mclass.h>
|
||||
#endif
|
||||
|
||||
SOFIA_BEGIN_DECLS
|
||||
|
||||
MSG_DLL extern msg_mclass_t const msg_multipart_mclass[1];
|
||||
|
||||
#define msg_multipart_class ((msg_hclass_t *)msg_multipart_mclass)
|
||||
|
||||
|
||||
/* Declare internal prototypes for #xxxxxxx_xxxxxxx# */
|
||||
|
||||
/**@addtogroup msg_#xxxxxx#
|
||||
* @{
|
||||
*/
|
||||
|
||||
enum {
|
||||
/** Hash of #xxxxxxx_xxxxxxx#. @internal */
|
||||
msg_#xxxxxx#_hash = #hash#
|
||||
};
|
||||
|
||||
/** Parse a #xxxxxxx_xxxxxxx#. @internal */
|
||||
MSG_DLL msg_parse_f msg_#xxxxxx#_d;
|
||||
|
||||
/** Print a #xxxxxxx_xxxxxxx#. @internal */
|
||||
MSG_DLL msg_print_f msg_#xxxxxx#_e;
|
||||
|
||||
MSG_DLL msg_xtra_f msg_#xxxxxx#_dup_xtra;
|
||||
MSG_DLL msg_dup_f msg_#xxxxxx#_dup_one;
|
||||
|
||||
/**Header class for #xxxxxxx_xxxxxxx#.
|
||||
*
|
||||
* The header class msg_#xxxxxx#_class defines how a
|
||||
* #xxxxxxx_xxxxxxx# header is parsed and printed. It also
|
||||
* contains methods used by message parser and other functions
|
||||
* to manipulate the #msg_#xxxxxx#_t header structure.
|
||||
*
|
||||
*/
|
||||
#ifndef msg_#xxxxxx#_class
|
||||
MSG_DLL extern msg_hclass_t msg_#xxxxxx#_class[];
|
||||
#endif
|
||||
|
||||
/**Initializer for an #msg_#xxxxxx#_t structure.
|
||||
*
|
||||
* A static msg_#xxxxxx#_t structure must be initialized
|
||||
* with the MSG_#XXXXXX#_INIT() macro. For instance,
|
||||
* @code
|
||||
*
|
||||
* msg_#xxxxxx#_t msg_#xxxxxx# = MSG_#XXXXXX#_INIT;
|
||||
*
|
||||
* @endcode
|
||||
* @HI
|
||||
*/
|
||||
#define MSG_#XXXXXX#_INIT() MSG_HDR_INIT(#xxxxxx#)
|
||||
|
||||
/**Initialize an #msg_#xxxxxx#_t structure.
|
||||
*
|
||||
* An #msg_#xxxxxx#_t structure can be initialized with the
|
||||
* msg_#xxxxxx#_init() function/macro. For instance,
|
||||
* @code
|
||||
*
|
||||
* msg_#xxxxxx#_t msg_#xxxxxx#;
|
||||
*
|
||||
* msg_#xxxxxx#_init(&msg_#xxxxxx#);
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* @param x pointer to #msg_#xxxxxx#_t structure
|
||||
*/
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_init(msg_#xxxxxx#_t x[1])
|
||||
{
|
||||
return MSG_HEADER_INIT(x, msg_#xxxxxx#_class, sizeof(msg_#xxxxxx#_t));
|
||||
}
|
||||
#else
|
||||
#define msg_#xxxxxx#_init(x) \
|
||||
MSG_HEADER_INIT(x, msg_#xxxxxx#_class, sizeof(msg_#xxxxxx#_t))
|
||||
#endif
|
||||
|
||||
/**Test if header object is an instance of #msg_#xxxxxx#_t.
|
||||
*
|
||||
* The function msg_is_#xxxxxx#() returns true (nonzero) if
|
||||
* the header class is an instance of #xxxxxxx_xxxxxxx#
|
||||
* object and false (zero) otherwise.
|
||||
*
|
||||
* @param header pointer to the header structure to be tested
|
||||
*
|
||||
* @return The function msg_is_#xxxxxx#() returns true (nonzero) if the
|
||||
* header object is an instance of header #xxxxxxx_xxxxxxx# and false (zero)
|
||||
* otherwise.
|
||||
*/
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline int msg_is_#xxxxxx#(msg_header_t const *header)
|
||||
{
|
||||
return header && header->sh_class->hc_hash == msg_#xxxxxx#_hash;
|
||||
}
|
||||
#else
|
||||
int msg_is_#xxxxxx#(msg_header_t const *header);
|
||||
#endif
|
||||
|
||||
#define msg_#xxxxxx#_p(h) msg_is_#xxxxxx#((h))
|
||||
|
||||
/**Duplicate (deep copy) #msg_#xxxxxx#_t.
|
||||
*
|
||||
* The function msg_#xxxxxx#_dup() duplicates a header structure @a
|
||||
* header. If the header structure @a header contains a reference
|
||||
* (@c header->x_next) to a list of headers, all the headers in the
|
||||
* list are duplicated, too.
|
||||
*
|
||||
* @param home memory home used to allocate new structure
|
||||
* @param header header structure to be duplicated
|
||||
*
|
||||
* When duplicating, all parameter lists and non-constant strings
|
||||
* attached to the header are copied, too. The function uses given
|
||||
* memory @a home to allocate all the memory areas used to copy the
|
||||
* header.
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
*
|
||||
* #xxxxxx# = msg_#xxxxxx#_dup(home, msg->msg_#xxxxxx#);
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* @return
|
||||
* The function msg_#xxxxxx#_dup() returns a pointer to the
|
||||
* newly duplicated #msg_#xxxxxx#_t header structure, or NULL
|
||||
* upon an error.
|
||||
*/
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline
|
||||
#endif
|
||||
msg_#xxxxxx#_t *msg_#xxxxxx#_dup(su_home_t *home,
|
||||
msg_#xxxxxx#_t const *header);
|
||||
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline
|
||||
msg_#xxxxxx#_t *msg_#xxxxxx#_dup(su_home_t *home,
|
||||
msg_#xxxxxx#_t const *header)
|
||||
{
|
||||
return (msg_#xxxxxx#_t *)
|
||||
msg_header_dup_as(home, msg_#xxxxxx#_class, (msg_header_t const *)header);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**Copy an #msg_#xxxxxx#_t header structure.
|
||||
*
|
||||
* The function msg_#xxxxxx#_copy() copies a header structure @a
|
||||
* header. If the header structure @a header contains a reference
|
||||
* (@c header->h_next) to a list of headers, all the headers in that
|
||||
* list are copied, too. The function uses given memory @a home to
|
||||
* allocate all the memory areas used to copy the header structure
|
||||
* @a header.
|
||||
*
|
||||
* @param home memory home used to allocate new structure
|
||||
* @param header pointer to the header structure to be duplicated
|
||||
*
|
||||
* When copying, only the header structure and parameter lists
|
||||
* attached to it are duplicated. The new header structure retains
|
||||
* all the references to the strings within the old @a header,
|
||||
* including the encoding of the old header, if present.
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
*
|
||||
* #xxxxxx# = msg_#xxxxxx#_copy(home, msg->msg_#xxxxxx#);
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* @return
|
||||
* The function msg_#xxxxxx#_copy() returns a pointer to
|
||||
* newly copied header structure, or NULL upon an error.
|
||||
*/
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline
|
||||
#endif
|
||||
msg_#xxxxxx#_t *msg_#xxxxxx#_copy(su_home_t *home,
|
||||
msg_#xxxxxx#_t const *header);
|
||||
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline
|
||||
msg_#xxxxxx#_t *msg_#xxxxxx#_copy(su_home_t *home,
|
||||
msg_#xxxxxx#_t const *header)
|
||||
{
|
||||
return (msg_#xxxxxx#_t *)
|
||||
msg_header_copy_as(home, msg_#xxxxxx#_class, (msg_header_t const *)header);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**Make a header structure #msg_#xxxxxx#_t.
|
||||
*
|
||||
* The function msg_#xxxxxx#_make() makes a new #msg_#xxxxxx#_t header
|
||||
* structure. It allocates a new header structure, and decodes the string @a
|
||||
* s as the value of the structure.
|
||||
*
|
||||
* @param home memory home used to allocate new header structure.
|
||||
* @param s string to be decoded as value of the new header structure
|
||||
*
|
||||
* @note This function may be implemented as a macro calling
|
||||
* msg_header_make().
|
||||
*
|
||||
* @return
|
||||
* The function msg_#xxxxxx#_make() returns a pointer to newly maked
|
||||
* #msg_#xxxxxx#_t header structure, or NULL upon an error.
|
||||
*/
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_make(su_home_t *home, char const *s)
|
||||
{
|
||||
return (msg_#xxxxxx#_t*)msg_header_make(home, msg_#xxxxxx#_class, s);
|
||||
}
|
||||
#else
|
||||
msg_#xxxxxx#_t *msg_#xxxxxx#_make(su_home_t *home, char const *s);
|
||||
#endif
|
||||
|
||||
|
||||
/**Make a #xxxxxxx_xxxxxxx# from formatting result.
|
||||
*
|
||||
* The function msg_#xxxxxx#_format() makes a new #xxxxxxx_xxxxxxx# object
|
||||
* using snprintf-formatted result as its value. The function first
|
||||
* prints the arguments according to the format @a fmt specified. Then it
|
||||
* allocates a new header structure, and uses the formatting result as the
|
||||
* header value.
|
||||
*
|
||||
* @param home memory home used to allocate new header structure.
|
||||
* @param fmt string used as a printf()-style format
|
||||
* @param ... argument list for format
|
||||
*
|
||||
* @note This function may be implemented as a macro calling
|
||||
* msg_header_format().
|
||||
*
|
||||
* @return
|
||||
* The function msg_#xxxxxx#_format() returns a pointer to newly
|
||||
* makes header structure, or NULL upon an error.
|
||||
*
|
||||
* @HIDE
|
||||
*/
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline
|
||||
#endif
|
||||
msg_#xxxxxx#_t *msg_#xxxxxx#_format(su_home_t *home, char const *fmt, ...)
|
||||
__attribute__((__format__ (printf, 2, 3)));
|
||||
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_format(su_home_t *home, char const *fmt, ...)
|
||||
{
|
||||
msg_header_t *h;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
h = msg_header_vformat(home, msg_#xxxxxx#_class, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return (msg_#xxxxxx#_t*)h;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
/* Internal prototypes */
|
||||
MSG_DLL msg_update_f msg_accept_update;
|
||||
MSG_DLL msg_update_f msg_accept_any_update;
|
||||
MSG_DLL msg_update_f msg_content_disposition_update;
|
||||
|
||||
SOFIA_END_DECLS
|
||||
|
||||
#endif /** !defined(MSG_MIME_PROTOS_H) */
|
||||
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MSG_PARSER_H
|
||||
/** Defined when <sofia-sip/msg_parser.h> has been included. */
|
||||
#define MSG_PARSER_H
|
||||
|
||||
/**@ingroup msg_parser
|
||||
* @file sofia-sip/msg_parser.h
|
||||
*
|
||||
* Message parser interface.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Tue Aug 21 16:03:45 2001 ppessi
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SU_ALLOC_H
|
||||
#include <sofia-sip/su_alloc.h>
|
||||
#endif
|
||||
#ifndef MSG_HEADER_H
|
||||
#include <sofia-sip/msg_header.h>
|
||||
#endif
|
||||
#ifndef BNF_H
|
||||
#include <sofia-sip/bnf.h>
|
||||
#endif
|
||||
#ifndef URL_H
|
||||
#include <sofia-sip/url.h>
|
||||
#endif
|
||||
|
||||
SOFIA_BEGIN_DECLS
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* 1) Header class definitions.
|
||||
*/
|
||||
|
||||
#if HAVE_STRUCT_KEYWORDS
|
||||
/** Define a header class */
|
||||
#define MSG_HEADER_CLASS(pr, c, l, s, params, kind, dup, upd) \
|
||||
{{ \
|
||||
hc_hash: pr##c##_hash, \
|
||||
hc_parse: pr##c##_d, \
|
||||
hc_print: pr##c##_e, \
|
||||
hc_dxtra: dup##_dup_xtra, \
|
||||
hc_dup_one: dup##_dup_one, \
|
||||
hc_update: upd##_update, \
|
||||
hc_name: l, \
|
||||
hc_len: sizeof(l) - 1, \
|
||||
hc_short: s, \
|
||||
hc_size: MSG_ALIGN(sizeof(pr##c##_t), sizeof(void*)), \
|
||||
hc_params: offsetof(pr##c##_t, params), \
|
||||
hc_kind: msg_kind_##kind, \
|
||||
}}
|
||||
#else
|
||||
#define MSG_HEADER_CLASS(pr, c, l, s, params, kind, dup, upd) \
|
||||
{{ \
|
||||
pr##c##_hash, \
|
||||
pr##c##_d, \
|
||||
pr##c##_e, \
|
||||
dup##_dup_xtra, \
|
||||
dup##_dup_one, \
|
||||
upd##_update, \
|
||||
l, \
|
||||
sizeof(l) - 1, \
|
||||
s, \
|
||||
MSG_ALIGN(sizeof(pr##c##_t), sizeof(void*)), \
|
||||
offsetof(pr##c##_t, params), \
|
||||
msg_kind_##kind, \
|
||||
}}
|
||||
#endif
|
||||
|
||||
/* Mark headers critical for understanding the message */
|
||||
#define msg_kind_single_critical msg_kind_single, 1
|
||||
#define msg_kind_list_critical msg_kind_list, 1
|
||||
|
||||
SOFIAPUBFUN issize_t msg_extract_header(msg_t *msg, msg_pub_t *mo,
|
||||
char b[], isize_t bsiz, int eos);
|
||||
SOFIAPUBFUN issize_t msg_extract_separator(msg_t *msg, msg_pub_t *mo,
|
||||
char b[], isize_t bsiz, int eos);
|
||||
SOFIAPUBFUN issize_t msg_extract_payload(msg_t *msg, msg_pub_t *mo,
|
||||
msg_header_t **return_payload,
|
||||
usize_t body_len,
|
||||
char b[], isize_t bsiz, int eos);
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* 2) Header processing methods for common headers.
|
||||
*/
|
||||
|
||||
SOFIAPUBFUN int msg_firstline_d(char *s, char **ss2, char **ss3);
|
||||
|
||||
SOFIAPUBFUN isize_t msg_default_dup_xtra(msg_header_t const *header, isize_t offset);
|
||||
SOFIAPUBFUN char *msg_default_dup_one(msg_header_t *dst,
|
||||
msg_header_t const *src,
|
||||
char *b,
|
||||
isize_t xtra);
|
||||
|
||||
SOFIAPUBFUN issize_t msg_numeric_d(su_home_t *, msg_header_t *h, char *s, isize_t slen);
|
||||
SOFIAPUBFUN issize_t msg_numeric_e(char [], isize_t, msg_header_t const *, int);
|
||||
|
||||
SOFIAPUBFUN issize_t msg_list_d(su_home_t *, msg_header_t *h, char *s, isize_t slen);
|
||||
SOFIAPUBFUN issize_t msg_list_e(char [], isize_t, msg_header_t const *, int);
|
||||
SOFIAPUBFUN isize_t msg_list_dup_xtra(msg_header_t const *h, isize_t offset);
|
||||
SOFIAPUBFUN char *msg_list_dup_one(msg_header_t *dst,
|
||||
msg_header_t const *src,
|
||||
char *b, isize_t xtra);
|
||||
|
||||
SOFIAPUBFUN issize_t msg_generic_d(su_home_t *, msg_header_t *, char *, isize_t);
|
||||
SOFIAPUBFUN issize_t msg_generic_e(char [], isize_t, msg_header_t const *, int);
|
||||
SOFIAPUBFUN isize_t msg_generic_dup_xtra(msg_header_t const *h, isize_t offset);
|
||||
SOFIAPUBFUN char *msg_generic_dup_one(msg_header_t *dst,
|
||||
msg_header_t const *src,
|
||||
char *b,
|
||||
isize_t xtra);
|
||||
|
||||
SOFIAPUBFUN isize_t msg_unknown_dup_xtra(msg_header_t const *h, isize_t offset);
|
||||
SOFIAPUBFUN char *msg_unknown_dup_one(msg_header_t *dst,
|
||||
msg_header_t const *src,
|
||||
char *b, isize_t xtra);
|
||||
|
||||
SOFIAPUBFUN isize_t msg_error_dup_xtra(msg_header_t const *h, isize_t offset);
|
||||
SOFIAPUBFUN char *msg_error_dup_one(msg_header_t *dst,
|
||||
msg_header_t const *src,
|
||||
char *b, isize_t xtra);
|
||||
|
||||
SOFIAPUBFUN issize_t msg_payload_d(su_home_t *, msg_header_t *h, char *s, isize_t slen);
|
||||
SOFIAPUBFUN issize_t msg_payload_e(char b[], isize_t bsiz, msg_header_t const *, int f);
|
||||
SOFIAPUBFUN isize_t msg_payload_dup_xtra(msg_header_t const *h, isize_t offset);
|
||||
SOFIAPUBFUN char *msg_payload_dup_one(msg_header_t *dst,
|
||||
msg_header_t const *src,
|
||||
char *b, isize_t xtra);
|
||||
|
||||
SOFIAPUBFUN issize_t msg_separator_d(su_home_t *, msg_header_t *, char *, isize_t);
|
||||
SOFIAPUBFUN issize_t msg_separator_e(char [], isize_t, msg_header_t const *, int);
|
||||
|
||||
SOFIAPUBFUN issize_t msg_auth_d(su_home_t *, msg_header_t *h, char *s, isize_t slen);
|
||||
SOFIAPUBFUN issize_t msg_auth_e(char b[], isize_t bsiz, msg_header_t const *h, int f);
|
||||
SOFIAPUBFUN isize_t msg_auth_dup_xtra(msg_header_t const *h, isize_t offset);
|
||||
SOFIAPUBFUN char *msg_auth_dup_one(msg_header_t *dst, msg_header_t const *src,
|
||||
char *b, isize_t xtra);
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* 2) Macros and prototypes for building header decoding/encoding functions.
|
||||
*/
|
||||
|
||||
#define MSG_HEADER_DATA(h) ((char *)(h) + (h)->sh_class->hc_size)
|
||||
|
||||
#define MSG_HEADER_TEST(h) ((h) && (h)->sh_class)
|
||||
|
||||
su_inline void *msg_header_data(msg_frg_t *h);
|
||||
|
||||
SOFIAPUBFUN int msg_hostport_d(char **ss,
|
||||
char const **return_host,
|
||||
char const **return_port);
|
||||
|
||||
SOFIAPUBFUN issize_t msg_token_d(char **ss, char const **return_token);
|
||||
SOFIAPUBFUN issize_t msg_uint32_d(char **ss, uint32_t *return_value);
|
||||
SOFIAPUBFUN issize_t msg_comment_d(char **ss, char const **return_comment);
|
||||
SOFIAPUBFUN issize_t msg_quoted_d(char **ss, char **return_unquoted);
|
||||
SOFIAPUBFUN issize_t msg_unquoted_e(char *b, isize_t bsiz, char const *s);
|
||||
|
||||
SOFIAPUBFUN issize_t msg_parse_next_field(su_home_t *home, msg_header_t *prev,
|
||||
char *s, isize_t slen);
|
||||
|
||||
/** Terminate encoding. @HI */
|
||||
#define MSG_TERM_E(p, e) ((p) < (e) ? (p)[0] = '\0' : '\0')
|
||||
|
||||
/** Encode a character. @HI */
|
||||
#define MSG_CHAR_E(p, e, c) (++(p) < (e) ? ((p)[-1]=(c)) : (c))
|
||||
|
||||
/** Calculate separator and string length. @HI */
|
||||
#define MSG_STRING_LEN(s, sep_size) ((s) ? (strlen(s) + sep_size) : 0)
|
||||
|
||||
/** Encode a string. @HI */
|
||||
#define MSG_STRING_E(p, e, s) do { \
|
||||
size_t _n = strlen(s); if (p + _n+1 < e) memcpy(p, s, _n+1); p+= _n; } while(0)
|
||||
|
||||
/** Duplicate string. @HI */
|
||||
#define MSG_STRING_DUP(p, d, s) \
|
||||
(void)((s)?((p)=(char*)memccpy((void *)((d)=(char*)p),(s),0,SIZE_MAX))\
|
||||
:((d)=NULL))
|
||||
|
||||
/** Calculate string size. @HI */
|
||||
#define MSG_STRING_SIZE(s) ((s) ? (strlen(s) + 1) : 0)
|
||||
|
||||
SOFIAPUBFUN issize_t msg_commalist_d(su_home_t *, char **ss,
|
||||
msg_param_t **append_list,
|
||||
issize_t (*scanner)(char *s));
|
||||
SOFIAPUBFUN issize_t msg_token_scan(char *start);
|
||||
SOFIAPUBFUN issize_t msg_attribute_value_scanner(char *s);
|
||||
|
||||
SOFIAPUBFUN issize_t msg_any_list_d(su_home_t *, char **ss,
|
||||
msg_param_t **append_list,
|
||||
issize_t (*scanner)(char *s),
|
||||
int sep);
|
||||
|
||||
/** Encode a comma-separated parameter list */
|
||||
#define MSG_COMMALIST_E(b, end, params, compact) do { \
|
||||
char const * const *p_; char const * c_ = ""; \
|
||||
for (p_ = (params); p_ && *p_; p_++, c_ = (compact ? "," : ", ")) \
|
||||
{ MSG_STRING_E(b, (end), c_); MSG_STRING_E(b, (end), *p_); } \
|
||||
} while(0)
|
||||
|
||||
/* Parameter lists */
|
||||
|
||||
SOFIAPUBFUN int msg_header_update_params(msg_common_t *h, int clear);
|
||||
|
||||
/** Match a parameter with any value. @HI */
|
||||
#define MSG_PARAM_MATCH(v, s, name) \
|
||||
(strncasecmp(s, name "=", sizeof(name)) == 0 ? (v = s + sizeof(name)) : NULL)
|
||||
|
||||
/** Match a parameter with known value. @HI */
|
||||
#define MSG_PARAM_MATCH_P(v, s, name) \
|
||||
((strncasecmp((s), name "", sizeof(name) - 1) == 0 && \
|
||||
((s)[sizeof(name) - 1] == '=' || (s)[sizeof(name) - 1] == '\0')) ? \
|
||||
((v) = 1) : 0)
|
||||
|
||||
/** Calculate allocated number of items in parameter list. @HI */
|
||||
#define MSG_PARAMS_NUM(n) (((n) + MSG_N_PARAMS - 1) & (size_t)(0 - MSG_N_PARAMS))
|
||||
|
||||
/** Parse a semicolong-separated attribute-value list. @HI */
|
||||
SOFIAPUBFUN issize_t msg_avlist_d(su_home_t *, char **ss,
|
||||
msg_param_t const **return_params);
|
||||
|
||||
/** Parse a semicolon-separated parameter list starting with semicolon. @HI */
|
||||
SOFIAPUBFUN issize_t msg_params_d(su_home_t *, char **ss,
|
||||
msg_param_t const **return_params);
|
||||
|
||||
/** Encode a list of parameters. */
|
||||
SOFIAPUBFUN isize_t msg_params_e(char b[], isize_t bsiz, msg_param_t const pparams[]);
|
||||
|
||||
/** Join list of parameters */
|
||||
SOFIAPUBFUN issize_t msg_params_join(su_home_t *,
|
||||
msg_param_t **dst,
|
||||
msg_param_t const *src,
|
||||
unsigned prune,
|
||||
int dup);
|
||||
|
||||
/** Encode a list of parameters. @HI */
|
||||
#define MSG_PARAMS_E(b, end, params, flags) \
|
||||
(b) += msg_params_e((b), (size_t)((b) < (end) ? (end) - (b) : 0), (params))
|
||||
|
||||
/** Calculate extra size of parametes. @HI */
|
||||
#define MSG_PARAMS_SIZE(rv, params) (rv = msg_params_dup_xtra(params, rv))
|
||||
|
||||
/** Duplicate a parameter list */
|
||||
SOFIAPUBFUN char *msg_params_dup(msg_param_t const **d, msg_param_t const *s,
|
||||
char *b, isize_t xtra);
|
||||
|
||||
/** Count number of parameters in the list */
|
||||
su_inline isize_t msg_params_count(msg_param_t const params[])
|
||||
{
|
||||
if (params) {
|
||||
size_t n;
|
||||
for (n = 0; params[n]; n++)
|
||||
;
|
||||
return n;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Calculate memory size required by parameter list */
|
||||
su_inline isize_t msg_params_dup_xtra(msg_param_t const params[], isize_t offset)
|
||||
{
|
||||
isize_t n = msg_params_count(params);
|
||||
if (n) {
|
||||
MSG_STRUCT_SIZE_ALIGN(offset);
|
||||
offset += MSG_PARAMS_NUM(n + 1) * sizeof(msg_param_t);
|
||||
for (n = 0; params[n]; n++)
|
||||
offset += strlen(params[n]) + 1;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
/** Return pointer to extra data after header structure */
|
||||
su_inline void *msg_header_data(msg_frg_t *h)
|
||||
{
|
||||
if (h)
|
||||
return (char *)h + h->h_class->hc_size;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SOFIA_END_DECLS
|
||||
|
||||
#endif /** MSG_PARSER_H */
|
||||
@@ -0,0 +1,311 @@
|
||||
/**@ingroup msg_headers -*- C -*-
|
||||
* @file sofia-sip/msg_protos.h.in
|
||||
*
|
||||
* Template for <msg_protos.h>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MSG_PROTOS_H
|
||||
/** Defined when <sofia-sip/msg_protos.h> has been included. */
|
||||
#define MSG_PROTOS_H
|
||||
|
||||
/**@ingroup msg_headers
|
||||
* @file sofia-sip/msg_protos.h
|
||||
*
|
||||
* Prototypes for common headers
|
||||
*
|
||||
* #AUTO#
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Fri Aug 16 19:18:26 EEST 2002 ppessi
|
||||
*/
|
||||
|
||||
#ifndef MSG_HEADER_H
|
||||
#include <sofia-sip/msg_header.h>
|
||||
#endif
|
||||
|
||||
SOFIA_BEGIN_DECLS
|
||||
|
||||
enum {
|
||||
msg_request_hash = -1,
|
||||
msg_status_hash = -2
|
||||
};
|
||||
|
||||
|
||||
/* Declare internal prototypes for #xxxxxxx_xxxxxxx# */
|
||||
|
||||
/**@addtogroup msg_#xxxxxx#
|
||||
* @{
|
||||
*/
|
||||
|
||||
enum {
|
||||
/** Hash of #xxxxxxx_xxxxxxx#. @internal */
|
||||
msg_#xxxxxx#_hash = #hash#
|
||||
};
|
||||
|
||||
/** Parse a #xxxxxxx_xxxxxxx#. @internal */
|
||||
MSG_DLL msg_parse_f msg_#xxxxxx#_d;
|
||||
|
||||
/** Print a #xxxxxxx_xxxxxxx#. @internal */
|
||||
MSG_DLL msg_print_f msg_#xxxxxx#_e;
|
||||
|
||||
/**Header class for #xxxxxxx_xxxxxxx#.
|
||||
*
|
||||
* The header class msg_#xxxxxx#_class defines how a
|
||||
* #xxxxxxx_xxxxxxx# header is parsed and printed. It also
|
||||
* contains methods used by message parser and other functions
|
||||
* to manipulate the msg_#xxxxxx#_t header structure.
|
||||
*
|
||||
*/
|
||||
MSG_DLL extern msg_hclass_t msg_#xxxxxx#_class[];
|
||||
|
||||
/**Initializer for structure msg_#xxxxxx#_t.
|
||||
*
|
||||
* A static msg_#xxxxxx#_t structure must be initialized
|
||||
* with the MSG_#XXXXXX#_INIT() macro. For instance,
|
||||
* @code
|
||||
*
|
||||
* msg_#xxxxxx#_t msg_#xxxxxx# = MSG_#XXXXXX#_INIT;
|
||||
*
|
||||
* @endcode
|
||||
* @HI
|
||||
*/
|
||||
#define MSG_#XXXXXX#_INIT() MSG_HDR_INIT(#xxxxxx#)
|
||||
|
||||
/**Initialize a structure msg_#xxxxxx#_t.
|
||||
*
|
||||
* An msg_#xxxxxx#_t structure can be initialized with the
|
||||
* msg_#xxxxxx#_init() function/macro. For instance,
|
||||
* @code
|
||||
*
|
||||
* msg_#xxxxxx#_t msg_#xxxxxx#;
|
||||
*
|
||||
* msg_#xxxxxx#_init(&msg_#xxxxxx#);
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* @param x pointer to msg_#xxxxxx#_t structure
|
||||
*/
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_init(msg_#xxxxxx#_t x[1])
|
||||
{
|
||||
return MSG_HEADER_INIT(x, msg_#xxxxxx#_class, sizeof(msg_#xxxxxx#_t));
|
||||
}
|
||||
#else
|
||||
#define msg_#xxxxxx#_init(x) \
|
||||
MSG_HEADER_INIT(x, msg_#xxxxxx#_class, sizeof(msg_#xxxxxx#_t))
|
||||
#endif
|
||||
|
||||
/**Test if header object is instance of msg_#xxxxxx#_t.
|
||||
*
|
||||
* The function msg_is_#xxxxxx#() returns true (nonzero) if
|
||||
* the header class is an instance of #xxxxxxx_xxxxxxx#
|
||||
* object and false (zero) otherwise.
|
||||
*
|
||||
* @param header pointer to the header structure to be tested
|
||||
*
|
||||
* @return
|
||||
* The function msg_is_#xxxxxx#() returns true (nonzero) if
|
||||
* the header object is an instance of header #xxxxxx# and
|
||||
* false (zero) otherwise.
|
||||
*/
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline int msg_is_#xxxxxx#(msg_header_t const *header)
|
||||
{
|
||||
msg_generic_t const *h = (msg_generic_t *)header;
|
||||
return h && h->g_common->h_class->hc_hash == msg_#xxxxxx#_hash;
|
||||
}
|
||||
#else
|
||||
int msg_is_#xxxxxx#(msg_header_t const *header);
|
||||
#endif
|
||||
|
||||
/**Duplicate (deep copy) @c msg_#xxxxxx#_t.
|
||||
*
|
||||
* The function msg_#xxxxxx#_dup() duplicates a header structure @a
|
||||
* header. If the header structure @a header contains a reference
|
||||
* (@c header->x_next) to a list of headers, all the headers in the
|
||||
* list are duplicated, too.
|
||||
*
|
||||
* @param home memory home used to allocate new structure
|
||||
* @param header header structure to be duplicated
|
||||
*
|
||||
* When duplicating, all parameter lists and non-constant strings
|
||||
* attached to the header are copied, too. The function uses given
|
||||
* memory @a home to allocate all the memory areas used to copy the
|
||||
* header.
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
*
|
||||
* #xxxxxx# = msg_#xxxxxx#_dup(home, msg->msg_#xxxxxx#);
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* @return
|
||||
* The function msg_#xxxxxx#_dup() returns a pointer to the
|
||||
* newly duplicated msg_#xxxxxx#_t header structure, or NULL
|
||||
* upon an error.
|
||||
*/
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline
|
||||
#endif
|
||||
msg_#xxxxxx#_t *msg_#xxxxxx#_dup(su_home_t *home,
|
||||
msg_#xxxxxx#_t const *header)
|
||||
__attribute__((__malloc__));
|
||||
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline
|
||||
msg_#xxxxxx#_t *msg_#xxxxxx#_dup(su_home_t *home,
|
||||
msg_#xxxxxx#_t const *header)
|
||||
{
|
||||
return (msg_#xxxxxx#_t *)
|
||||
msg_header_dup_as(home, msg_#xxxxxx#_class, (msg_header_t const *)header);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**Copy a msg_#xxxxxx#_t header structure.
|
||||
*
|
||||
* The function msg_#xxxxxx#_copy() copies a header structure @a
|
||||
* header. If the header structure @a header contains a reference
|
||||
* (@c header->h_next) to a list of headers, all the headers in that
|
||||
* list are copied, too. The function uses given memory @a home to
|
||||
* allocate all the memory areas used to copy the header structure
|
||||
* @a header.
|
||||
*
|
||||
* @param home memory home used to allocate new structure
|
||||
* @param header pointer to the header structure to be duplicated
|
||||
*
|
||||
* When copying, only the header structure and parameter lists
|
||||
* attached to it are duplicated. The new header structure retains
|
||||
* all the references to the strings within the old @a header,
|
||||
* including the encoding of the old header, if present.
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
*
|
||||
* #xxxxxx# = msg_#xxxxxx#_copy(home, msg->msg_#xxxxxx#);
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* @return
|
||||
* The function msg_#xxxxxx#_copy() returns a pointer to
|
||||
* newly copied header structure, or NULL upon an error.
|
||||
*/
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline
|
||||
#endif
|
||||
msg_#xxxxxx#_t *msg_#xxxxxx#_copy(su_home_t *home,
|
||||
msg_#xxxxxx#_t const *header)
|
||||
__attribute__((__malloc__));
|
||||
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline
|
||||
msg_#xxxxxx#_t *msg_#xxxxxx#_copy(su_home_t *home,
|
||||
msg_#xxxxxx#_t const *header)
|
||||
{
|
||||
return (msg_#xxxxxx#_t *)
|
||||
msg_header_copy_as(home, msg_#xxxxxx#_class, (msg_header_t const *)header);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**Make a header structure msg_#xxxxxx#_t.
|
||||
*
|
||||
* The function msg_#xxxxxx#_make() makes a new
|
||||
* msg_#xxxxxx#_t header structure. It allocates a new
|
||||
* header structure, and decodes the string @a s as the
|
||||
* value of the structure.
|
||||
*
|
||||
* @param home memory home used to allocate new header structure.
|
||||
* @param s string to be decoded as value of the new header structure
|
||||
*
|
||||
* @note This function is usually implemented as a macro calling
|
||||
* msg_header_make().
|
||||
*
|
||||
* @return
|
||||
* The function msg_#xxxxxx#_make() returns a pointer to
|
||||
* newly maked msg_#xxxxxx#_t header structure, or NULL upon
|
||||
* an error.
|
||||
*/
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_make(su_home_t *home, char const *s)
|
||||
{
|
||||
return (msg_#xxxxxx#_t*)msg_header_make(home, msg_#xxxxxx#_class, s);
|
||||
}
|
||||
#else
|
||||
msg_#xxxxxx#_t *msg_#xxxxxx#_make(su_home_t *home, char const *s)
|
||||
__attribute__((__malloc__));
|
||||
#endif
|
||||
|
||||
/**Make a #xxxxxxx_xxxxxxx# from formatting result.
|
||||
*
|
||||
* The function msg_#xxxxxx#_format() makes a new
|
||||
* #xxxxxxx_xxxxxxx# object using formatting result as its
|
||||
* value. The function first prints the arguments according to
|
||||
* the format @a fmt specified. Then it allocates a new header
|
||||
* structure, and uses the formatting result as the header
|
||||
* value.
|
||||
*
|
||||
* @param home memory home used to allocate new header structure.
|
||||
* @param fmt string used as a printf()-style format
|
||||
* @param ... argument list for format
|
||||
*
|
||||
* @note This function is usually implemented as a macro calling
|
||||
* msg_header_format().
|
||||
*
|
||||
* @return
|
||||
* The function msg_#xxxxxx#_format() returns a pointer to newly
|
||||
* makes header structure, or NULL upon an error.
|
||||
*
|
||||
* @HIDE
|
||||
*/
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline
|
||||
#endif
|
||||
msg_#xxxxxx#_t *msg_#xxxxxx#_format(su_home_t *home, char const *fmt, ...)
|
||||
__attribute__((__malloc__, __format__ (printf, 2, 3)));
|
||||
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_format(su_home_t *home, char const *fmt, ...)
|
||||
{
|
||||
msg_header_t *h;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
h = msg_header_vformat(home, msg_#xxxxxx#_class, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return (msg_#xxxxxx#_t*)h;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
SOFIA_END_DECLS
|
||||
|
||||
#endif /** !defined(MSG_PROTOS_H) */
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MSG_TAG_CLASS_H
|
||||
/** Defined when <sofia-sip/msg_tag_class.h> has been included */
|
||||
#define MSG_TAG_CLASS_H
|
||||
|
||||
/**@file sofia-sip/msg_tag_class.h
|
||||
* @brief Functions for constructing per-protocol tag classes.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Wed Feb 21 11:01:45 2001 ppessi
|
||||
*/
|
||||
|
||||
#ifndef SU_TAG_H
|
||||
#include <sofia-sip/su_tag.h>
|
||||
#endif
|
||||
|
||||
SOFIA_BEGIN_DECLS
|
||||
|
||||
SOFIAPUBFUN int msghdrtag_snprintf(tagi_t const *t, char b[], size_t size);
|
||||
SOFIAPUBFUN size_t msghdrtag_xtra(tagi_t const *t, size_t offset);
|
||||
SOFIAPUBFUN tagi_t *msghdrtag_dup(tagi_t *dst, tagi_t const *src,
|
||||
void **inout_buffer);
|
||||
SOFIAPUBFUN int msghdrtag_scan(tag_type_t tt, su_home_t *home,
|
||||
char const *s,
|
||||
tag_value_t *return_value);
|
||||
SOFIAPUBFUN tagi_t *msghdrtag_filter(tagi_t *dst, tagi_t const f[],
|
||||
tagi_t const *src,
|
||||
void **inout_buffer);
|
||||
|
||||
SOFIAPUBFUN tagi_t *msgstrtag_filter(tagi_t *dst, tagi_t const f[],
|
||||
tagi_t const *src,
|
||||
void **inout_buffer);
|
||||
|
||||
SOFIAPUBFUN int msgobjtag_snprintf(tagi_t const *t, char b[], size_t size);
|
||||
SOFIAPUBFUN size_t msgobjtag_xtra(tagi_t const *t, size_t offset);
|
||||
SOFIAPUBFUN tagi_t *msgobjtag_dup(tagi_t *dst, tagi_t const *src,
|
||||
void **inout_buffer);
|
||||
|
||||
SOFIA_END_DECLS
|
||||
|
||||
#endif /** !defined(MSG_TAG_CLASS_H) */
|
||||
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MSG_TYPES_H
|
||||
/** Defined when <sofia-sip/msg_types.h> has been included. */
|
||||
#define MSG_TYPES_H
|
||||
|
||||
/**@file sofia-sip/msg_types.h
|
||||
* @brief Types for messages and common headers
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Thu Jan 23 15:43:17 2003 ppessi
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SU_TYPES_H
|
||||
#include <sofia-sip/su_types.h>
|
||||
#endif
|
||||
|
||||
SOFIA_BEGIN_DECLS
|
||||
|
||||
/** Message class. */
|
||||
typedef struct msg_mclass_s msg_mclass_t;
|
||||
|
||||
/** Header class. */
|
||||
typedef struct msg_hclass_s const msg_hclass_t;
|
||||
|
||||
/** Header reference. */
|
||||
typedef struct msg_href_s msg_href_t;
|
||||
|
||||
/** Message object. */
|
||||
typedef struct msg_s msg_t;
|
||||
|
||||
#ifndef MSG_TIME_T_DEFINED
|
||||
#define MSG_TIME_T_DEFINED
|
||||
/** Time in seconds since epoch (1900-Jan-01 00:00:00). */
|
||||
typedef unsigned long msg_time_t;
|
||||
#endif
|
||||
|
||||
#ifndef MSG_TIME_MAX
|
||||
/** Latest time that can be expressed with msg_time_t. @HIDE */
|
||||
#define MSG_TIME_MAX ((msg_time_t)ULONG_MAX)
|
||||
#endif
|
||||
|
||||
#ifndef MSG_PUB_T
|
||||
#ifdef MSG_OBJ_T
|
||||
#define MSG_PUB_T MSG_OBJ_T
|
||||
#else
|
||||
#define MSG_PUB_T struct msg_pub_s
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**Public protocol-specific message structure for accessing the message.
|
||||
*
|
||||
* This type can be either #sip_t, #http_t, or #msg_multipart_t, depending
|
||||
* on the message. The base structure used by msg module is defined in
|
||||
* struct #msg_pub_s.
|
||||
*/
|
||||
typedef MSG_PUB_T msg_pub_t;
|
||||
|
||||
#ifndef MSG_HDR_T
|
||||
#define MSG_HDR_T union msg_header_u
|
||||
#endif
|
||||
/** Any protocol-specific header object */
|
||||
typedef MSG_HDR_T msg_header_t;
|
||||
|
||||
typedef struct msg_common_s msg_common_t;
|
||||
|
||||
typedef struct msg_separator_s msg_separator_t;
|
||||
typedef struct msg_payload_s msg_payload_t;
|
||||
typedef struct msg_unknown_s msg_unknown_t;
|
||||
typedef struct msg_error_s msg_error_t;
|
||||
|
||||
typedef msg_common_t msg_frg_t;
|
||||
|
||||
typedef char const *msg_param_t;
|
||||
typedef struct msg_numeric_s msg_numeric_t;
|
||||
typedef struct msg_generic_s msg_generic_t;
|
||||
typedef struct msg_list_s msg_list_t;
|
||||
typedef struct msg_auth_s msg_auth_t;
|
||||
typedef struct msg_auth_info_s msg_auth_info_t;
|
||||
|
||||
#define MSG_HEADER_N 16377
|
||||
|
||||
/** Common part of the header objects (or message fragments).
|
||||
*
|
||||
* This structure is also known as #msg_common_t or #sip_common_t.
|
||||
*/
|
||||
struct msg_common_s {
|
||||
msg_header_t *h_succ; /**< Pointer to succeeding fragment. */
|
||||
msg_header_t **h_prev; /**< Pointer to preceeding fragment. */
|
||||
msg_hclass_t *h_class; /**< Header class. */
|
||||
void const *h_data; /**< Fragment data */
|
||||
usize_t h_len; /**< Fragment length (including CRLF) */
|
||||
};
|
||||
|
||||
|
||||
/** Message object, common view */
|
||||
struct msg_pub_s {
|
||||
msg_common_t msg_common[1]; /**< Recursive */
|
||||
msg_pub_t *msg_next;
|
||||
void *msg_user;
|
||||
unsigned msg_size;
|
||||
unsigned msg_flags;
|
||||
msg_error_t *msg_error;
|
||||
msg_header_t *msg_request;
|
||||
msg_header_t *msg_status;
|
||||
msg_header_t *msg_headers[MSG_HEADER_N];
|
||||
};
|
||||
|
||||
#define msg_ident msg_common->h_class
|
||||
|
||||
/** Numeric header.
|
||||
*
|
||||
* A numeric header has a 32-bit integer as its value.
|
||||
*/
|
||||
struct msg_numeric_s {
|
||||
msg_common_t x_common[1]; /**< Common fragment info */
|
||||
msg_numeric_t *x_next; /**< Link to next header */
|
||||
unsigned long x_value; /**< Numeric header value */
|
||||
};
|
||||
|
||||
/** Generic header.
|
||||
*
|
||||
* A generic header does not have any internal structure. Its value is
|
||||
* represented as a string.
|
||||
*/
|
||||
struct msg_generic_s {
|
||||
msg_common_t g_common[1]; /**< Common fragment info */
|
||||
msg_generic_t *g_next; /**< Link to next header */
|
||||
char const *g_string; /**< Header value */
|
||||
};
|
||||
|
||||
/** List header.
|
||||
*
|
||||
* A list header consists of comma-separated list of tokens.
|
||||
*/
|
||||
struct msg_list_s {
|
||||
msg_common_t k_common[1]; /**< Common fragment info */
|
||||
msg_list_t *k_next; /**< Link to next header */
|
||||
msg_param_t *k_items; /**< List of items */
|
||||
};
|
||||
|
||||
/** Authentication header.
|
||||
*
|
||||
* An authentication header has authentication scheme name and
|
||||
* comma-separated list of parameters as its value.
|
||||
*/
|
||||
struct msg_auth_s {
|
||||
msg_common_t au_common[1]; /**< Common fragment info */
|
||||
msg_auth_t *au_next; /**< Link to next header */
|
||||
char const *au_scheme; /**< Auth-scheme like Basic or Digest */
|
||||
msg_param_t const *au_params; /**< Comma-separated parameters */
|
||||
};
|
||||
|
||||
/**Authentication-Info header
|
||||
*
|
||||
* An Authentication-Info header has comma-separated list of parameters as its value.
|
||||
*/
|
||||
struct msg_auth_info_s
|
||||
{
|
||||
msg_common_t ai_common[1]; /**< Common fragment info */
|
||||
msg_error_t *ai_next; /**< Dummy link to next */
|
||||
msg_param_t const *ai_params; /**< List of ainfo */
|
||||
};
|
||||
|
||||
/** Unknown header. */
|
||||
struct msg_unknown_s {
|
||||
msg_common_t un_common[1]; /**< Common fragment info */
|
||||
msg_unknown_t *un_next; /**< Link to next unknown header */
|
||||
char const *un_name; /**< Header name */
|
||||
char const *un_value; /**< Header field value */
|
||||
};
|
||||
|
||||
/** Erroneus header. */
|
||||
struct msg_error_s {
|
||||
msg_common_t er_common[1]; /**< Common fragment info */
|
||||
msg_error_t *er_next; /**< Link to next header */
|
||||
char const *er_name; /**< Name of bad header (if any). */
|
||||
};
|
||||
|
||||
|
||||
/** Separator. */
|
||||
struct msg_separator_s {
|
||||
msg_common_t sep_common[1]; /**< Common fragment info */
|
||||
msg_error_t *sep_next; /**< Dummy link to next header */
|
||||
char sep_data[4]; /**< NUL-terminated separator */
|
||||
};
|
||||
|
||||
/** Message payload. */
|
||||
struct msg_payload_s {
|
||||
msg_common_t pl_common[1]; /**< Common fragment info */
|
||||
msg_payload_t *pl_next; /**< Next payload chunk */
|
||||
char *pl_data; /**< Data - may contain NUL */
|
||||
usize_t pl_len; /**< Length of message payload */
|
||||
};
|
||||
|
||||
/** Any header. */
|
||||
union msg_header_u {
|
||||
msg_common_t sh_common[1]; /**< Common fragment info */
|
||||
struct {
|
||||
msg_common_t shn_common;
|
||||
msg_header_t *shn_next;
|
||||
} sh_header_next[1];
|
||||
#define sh_next sh_header_next->shn_next
|
||||
#define sh_class sh_common->h_class
|
||||
#define sh_succ sh_common->h_succ
|
||||
#define sh_prev sh_common->h_prev
|
||||
#define sh_data sh_common->h_data
|
||||
#define sh_len sh_common->h_len
|
||||
|
||||
msg_generic_t sh_generic[1];
|
||||
msg_numeric_t sh_numeric[1];
|
||||
msg_list_t sh_list[1];
|
||||
msg_auth_t sh_auth[1];
|
||||
msg_separator_t sh_separator[1];
|
||||
msg_payload_t sh_payload[1];
|
||||
msg_unknown_t sh_unknown[1];
|
||||
msg_error_t sh_error[1];
|
||||
};
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
/**Define how to handle existing headers
|
||||
* when a new header is added to a message.
|
||||
*/
|
||||
typedef enum {
|
||||
msg_kind_single, /**< Only one header is allowed */
|
||||
msg_kind_append, /**< New header is appended */
|
||||
msg_kind_list, /**< A token list header,
|
||||
* new header is combined with old one. */
|
||||
msg_kind_apndlist, /**< A complex list header. */
|
||||
msg_kind_prepend /**< New header is prepended */
|
||||
} msg_header_kind_t;
|
||||
|
||||
struct su_home_s;
|
||||
|
||||
typedef issize_t msg_parse_f(struct su_home_s *, msg_header_t *, char *, isize_t);
|
||||
typedef issize_t msg_print_f(char buf[], isize_t bufsiz,
|
||||
msg_header_t const *, int flags);
|
||||
typedef char *msg_dup_f(msg_header_t *dst, msg_header_t const *src,
|
||||
char *buf, isize_t bufsiz);
|
||||
typedef isize_t msg_xtra_f(msg_header_t const *h, isize_t offset);
|
||||
|
||||
typedef int msg_update_f(msg_common_t *, char const *name, isize_t namelen,
|
||||
char const *value);
|
||||
|
||||
/** Factory object for a header.
|
||||
*
|
||||
* The #msg_hclass_t object, "header class", defines how a header is
|
||||
* handled. It has parsing and printing functions, functions used to copy
|
||||
* header objects, header name and other information used when parsing,
|
||||
* printing, removing, adding and replacing headers within a message.
|
||||
*/
|
||||
struct msg_hclass_s
|
||||
{
|
||||
/* XXX size of header class missing. Someone has saved bits in wrong place. */
|
||||
int hc_hash; /**< Header name hash or ID */
|
||||
msg_parse_f *hc_parse; /**< Parse header. */
|
||||
msg_print_f *hc_print; /**< Print header. */
|
||||
msg_xtra_f *hc_dxtra; /**< Calculate extra size for dup */
|
||||
msg_dup_f *hc_dup_one; /**< Duplicate one header. */
|
||||
msg_update_f *hc_update; /**< Update parameter(s) */
|
||||
char const *hc_name; /**< Full name. */
|
||||
short hc_len; /**< Length of hc_name. */
|
||||
char hc_short[2];/**< Short name, if any. */
|
||||
unsigned char hc_size; /**< Size of header structure. */
|
||||
unsigned char hc_params; /**< Offset of parameter list */
|
||||
unsigned hc_kind:3; /**< Kind of header (#msg_header_kind_t):
|
||||
* single, append, list, apndlist, prepend. */
|
||||
unsigned hc_critical:1; /**< True if header is critical */
|
||||
unsigned /*pad*/:0;
|
||||
};
|
||||
|
||||
#define HC_LEN_MAX SHRT_MAX
|
||||
|
||||
SOFIA_END_DECLS
|
||||
|
||||
#endif /* !defined MSG_TYPES_H */
|
||||
@@ -0,0 +1,413 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 test_msg
|
||||
* @file test_class.c
|
||||
*
|
||||
* Message class for testing parser and transports.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Tue Mar 5 11:57:20 2002 ppessi
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define TAG_NAMESPACE "tst"
|
||||
|
||||
#include <test_class.h>
|
||||
#include <sofia-sip/msg_parser.h>
|
||||
#include <sofia-sip/msg_mclass.h>
|
||||
#include <test_protos.h>
|
||||
#include <sofia-sip/msg_addr.h>
|
||||
|
||||
extern msg_mclass_t const msg_test_mclass[1];
|
||||
|
||||
extern msg_mclass_t const *msg_test_default(void)
|
||||
{
|
||||
return msg_test_mclass;
|
||||
}
|
||||
|
||||
#define msg_generic_update NULL
|
||||
|
||||
/**@ingroup test_msg
|
||||
* @defgroup msg_test_request Request Line for Testing
|
||||
*/
|
||||
|
||||
static msg_xtra_f msg_request_dup_xtra;
|
||||
static msg_dup_f msg_request_dup_one;
|
||||
|
||||
msg_hclass_t msg_request_class[] =
|
||||
MSG_HEADER_CLASS(msg_, request, NULL, "", rq_common,
|
||||
single_critical, msg_request, msg_generic);
|
||||
|
||||
/** Decode a request line */
|
||||
issize_t msg_request_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen)
|
||||
{
|
||||
msg_request_t *rq = (msg_request_t *)h;
|
||||
char *uri, *version;
|
||||
|
||||
if (msg_firstline_d(s, &uri, &version) < 0 || !uri ||
|
||||
url_d(rq->rq_url, uri) < 0)
|
||||
return -1;
|
||||
|
||||
rq->rq_method_name = s;
|
||||
rq->rq_version = version;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Encode a request line. */
|
||||
issize_t msg_request_e(char b[], isize_t bsiz, msg_header_t const *h, int flags)
|
||||
{
|
||||
msg_request_t const *rq = (msg_request_t const *)h;
|
||||
|
||||
return snprintf(b, bsiz, "%s " URL_FORMAT_STRING " %s" CRLF,
|
||||
rq->rq_method_name,
|
||||
URL_PRINT_ARGS(rq->rq_url),
|
||||
rq->rq_version);
|
||||
}
|
||||
|
||||
isize_t msg_request_dup_xtra(msg_header_t const *h, isize_t offset)
|
||||
{
|
||||
isize_t rv = offset;
|
||||
msg_request_t const *rq = (msg_request_t const *)h;
|
||||
|
||||
rv += url_xtra(rq->rq_url);
|
||||
rv += MSG_STRING_SIZE(rq->rq_method_name);
|
||||
rv += MSG_STRING_SIZE(rq->rq_version);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** Duplicate one request header. */
|
||||
char *msg_request_dup_one(msg_header_t *dst, msg_header_t const *src,
|
||||
char *b, isize_t xtra)
|
||||
{
|
||||
msg_request_t *rq = (msg_request_t *)dst;
|
||||
msg_request_t const *o = (msg_request_t const *)src;
|
||||
char *end = b + xtra;
|
||||
|
||||
URL_DUP(b, end, rq->rq_url, o->rq_url);
|
||||
|
||||
MSG_STRING_DUP(b, rq->rq_method_name, o->rq_method_name);
|
||||
MSG_STRING_DUP(b, rq->rq_version, o->rq_version);
|
||||
|
||||
assert(b <= end);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/**@ingroup test_msg
|
||||
* @defgroup msg_test_status Status Line for Testing
|
||||
*/
|
||||
|
||||
static msg_xtra_f msg_status_dup_xtra;
|
||||
static msg_dup_f msg_status_dup_one;
|
||||
|
||||
msg_hclass_t msg_status_class[1] =
|
||||
MSG_HEADER_CLASS(msg_, status, NULL, "", st_common,
|
||||
single_critical, msg_status, msg_generic);
|
||||
|
||||
/** Parse status line */
|
||||
issize_t msg_status_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen)
|
||||
{
|
||||
msg_status_t *st = (msg_status_t *)h;
|
||||
char *status, *phrase;
|
||||
unsigned long code;
|
||||
|
||||
if (msg_firstline_d(s, &status, &phrase) < 0 ||
|
||||
(code = strtoul(status, &status, 10)) >= 1000 || *status)
|
||||
return -1;
|
||||
|
||||
st->st_status = code;
|
||||
st->st_phrase = phrase;
|
||||
st->st_version = s;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
issize_t msg_status_e(char b[], isize_t bsiz, msg_header_t const *h, int flags)
|
||||
{
|
||||
msg_status_t const *st = (msg_status_t const *)h;
|
||||
int status = st->st_status;
|
||||
|
||||
if (status > 999 || status < 100)
|
||||
status = 0;
|
||||
|
||||
return snprintf(b, bsiz, "%s %03u %s" CRLF,
|
||||
st->st_version, status, st->st_phrase);
|
||||
}
|
||||
|
||||
/** Extra size of a msg_status_t object. */
|
||||
isize_t msg_status_dup_xtra(msg_header_t const *h, isize_t offset)
|
||||
{
|
||||
isize_t rv = offset;
|
||||
msg_status_t const *st = (msg_status_t const *)h;
|
||||
rv += MSG_STRING_SIZE(st->st_version);
|
||||
rv += MSG_STRING_SIZE(st->st_phrase);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** Duplicate one status header. */
|
||||
char *msg_status_dup_one(msg_header_t *dst, msg_header_t const *src,
|
||||
char *b, isize_t xtra)
|
||||
{
|
||||
msg_status_t *st = (msg_status_t *)dst;
|
||||
msg_status_t const *o = (msg_status_t const *)src;
|
||||
char *end = b + xtra;
|
||||
|
||||
MSG_STRING_DUP(b, st->st_version, o->st_version);
|
||||
st->st_status = o->st_status;
|
||||
MSG_STRING_DUP(b, st->st_phrase, o->st_phrase);
|
||||
|
||||
assert(b <= end); (void)end;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/** Extract the message body, including separator line.
|
||||
*
|
||||
* @param[in,out] msg message object
|
||||
* @param[in,out] pub public message structure
|
||||
* @param[in] b buffer containing unparsed data
|
||||
* @param[in] bsiz buffer size
|
||||
* @param[in] eos true if buffer contains whole message
|
||||
*
|
||||
* @retval -1 error
|
||||
* @retval 0 message is incomplete
|
||||
* @retval other number of bytes extracted
|
||||
*/
|
||||
issize_t msg_test_extract_body(msg_t *msg, msg_pub_t *pub,
|
||||
char b[], isize_t bsiz, int eos)
|
||||
{
|
||||
msg_test_t *tst = (msg_test_t *)pub;
|
||||
ssize_t m = 0;
|
||||
size_t body_len;
|
||||
|
||||
if (!(tst->msg_flags & MSG_FLG_BODY)) {
|
||||
/* We are looking at a potential empty line */
|
||||
m = msg_extract_separator(msg, (msg_pub_t *)tst, b, bsiz, eos);
|
||||
if (m == 0 || m == -1)
|
||||
return m;
|
||||
tst->msg_flags |= MSG_FLG_BODY;
|
||||
b += m;
|
||||
bsiz -= m;
|
||||
}
|
||||
|
||||
if (tst->msg_content_length)
|
||||
body_len = tst->msg_content_length->l_length;
|
||||
else if (MSG_IS_MAILBOX(tst->msg_flags)) /* message fragments */
|
||||
body_len = 0;
|
||||
else if (eos)
|
||||
body_len = bsiz;
|
||||
else
|
||||
return -1;
|
||||
|
||||
if (body_len == 0) {
|
||||
tst->msg_flags |= MSG_FLG_COMPLETE;
|
||||
return m;
|
||||
}
|
||||
|
||||
if (m)
|
||||
return m;
|
||||
|
||||
if ((m = msg_extract_payload(msg, (msg_pub_t *)tst, NULL, body_len, b, bsiz, eos) ) == -1)
|
||||
return -1;
|
||||
|
||||
tst->msg_flags |= MSG_FLG_FRAGS;
|
||||
if (bsiz >= body_len)
|
||||
tst->msg_flags |= MSG_FLG_COMPLETE;
|
||||
return m;
|
||||
}
|
||||
|
||||
msg_href_t const msg_content_length_href[1] =
|
||||
{{
|
||||
msg_content_length_class,
|
||||
offsetof(msg_test_t, msg_content_length)
|
||||
}};
|
||||
|
||||
#include <sofia-sip/su_tag_class.h>
|
||||
#include <sofia-sip/su_tag_inline.h>
|
||||
#include <sofia-sip/su_tagarg.h>
|
||||
#include <sofia-sip/msg_tag_class.h>
|
||||
|
||||
tagi_t *tsttag_filter(tagi_t *dst,
|
||||
tagi_t const f[],
|
||||
tagi_t const *src,
|
||||
void **bb);
|
||||
|
||||
/** Tag class for test header tags. @HIDE */
|
||||
tag_class_t tsthdrtag_class[1] =
|
||||
{{
|
||||
sizeof(tsthdrtag_class),
|
||||
/* tc_next */ NULL,
|
||||
/* tc_len */ NULL,
|
||||
/* tc_move */ NULL,
|
||||
/* tc_xtra */ msghdrtag_xtra,
|
||||
/* tc_dup */ msghdrtag_dup,
|
||||
/* tc_free */ NULL,
|
||||
/* tc_find */ NULL,
|
||||
/* tc_snprintf */ msghdrtag_snprintf,
|
||||
/* tc_filter */ tsttag_filter,
|
||||
/* tc_ref_set */ t_ptr_ref_set,
|
||||
/* tc_scan */ msghdrtag_scan,
|
||||
}};
|
||||
|
||||
/** Tag class for TST header string tags. @HIDE */
|
||||
tag_class_t tststrtag_class[1] =
|
||||
{{
|
||||
sizeof(tststrtag_class),
|
||||
/* tc_next */ NULL,
|
||||
/* tc_len */ NULL,
|
||||
/* tc_move */ NULL,
|
||||
/* tc_xtra */ t_str_xtra,
|
||||
/* tc_dup */ t_str_dup,
|
||||
/* tc_free */ NULL,
|
||||
/* tc_find */ NULL,
|
||||
/* tc_snprintf */ t_str_snprintf,
|
||||
/* tc_filter */ NULL /* msgtag_str_filter */,
|
||||
/* tc_ref_set */ t_ptr_ref_set,
|
||||
/* tc_scan */ t_str_scan
|
||||
}};
|
||||
|
||||
/** Tag class for TST message tags. @HIDE */
|
||||
tag_class_t tstmsgtag_class[1] =
|
||||
{{
|
||||
sizeof(tstmsgtag_class),
|
||||
/* tc_next */ NULL,
|
||||
/* tc_len */ NULL,
|
||||
/* tc_move */ NULL,
|
||||
/* tc_xtra */ msgobjtag_xtra,
|
||||
/* tc_dup */ msgobjtag_dup,
|
||||
/* tc_free */ NULL,
|
||||
/* tc_find */ NULL,
|
||||
/* tc_snprintf */ msgobjtag_snprintf,
|
||||
/* tc_filter */ NULL /* tsttag_tst_filter */,
|
||||
/* tc_ref_set */ t_ptr_ref_set,
|
||||
}};
|
||||
|
||||
tag_typedef_t tsttag_header =
|
||||
{{ TAG_NAMESPACE, "header", tsthdrtag_class, 0 }};
|
||||
|
||||
tag_typedef_t tsttag_header_str = STRTAG_TYPEDEF(header_str);
|
||||
|
||||
/** Filter a TST header structure. */
|
||||
tagi_t *tsttag_filter(tagi_t *dst,
|
||||
tagi_t const f[],
|
||||
tagi_t const *src,
|
||||
void **bb)
|
||||
{
|
||||
tagi_t stub[2] = {{ NULL }};
|
||||
tag_type_t sctt, tt = f->t_tag;
|
||||
msg_hclass_t *hc = (msg_hclass_t *)tt->tt_magic;
|
||||
|
||||
assert(src);
|
||||
|
||||
sctt = src->t_tag;
|
||||
|
||||
if (sctt && sctt->tt_class == tstmsgtag_class) {
|
||||
msg_test_t const *tst = (msg_test_t const *)src->t_value;
|
||||
msg_mclass_t *mc = (msg_mclass_t *)tst->msg_ident;
|
||||
msg_header_t const **hh = (msg_header_t const **)
|
||||
msg_hclass_offset(mc, (msg_pub_t *)tst, hc);
|
||||
msg_header_t const *h;
|
||||
|
||||
if (tst == NULL ||
|
||||
(char *)hh >= ((char *)tst + tst->msg_size) ||
|
||||
(char *)hh < (char const *)&tst->msg_request)
|
||||
return dst;
|
||||
|
||||
h = *hh;
|
||||
|
||||
if (h == NULL)
|
||||
return dst;
|
||||
|
||||
stub[0].t_tag = tt;
|
||||
stub[0].t_value = (tag_value_t)h;
|
||||
src = stub; sctt = tt;
|
||||
}
|
||||
|
||||
if (tt != sctt)
|
||||
return dst;
|
||||
|
||||
if (!src->t_value)
|
||||
return dst;
|
||||
else if (dst) {
|
||||
return t_dup(dst, src, bb);
|
||||
}
|
||||
else {
|
||||
*bb = (char *)*bb + t_xtra(src, (size_t)*bb);
|
||||
return dst + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Add duplicates of headers from taglist to the TST message. */
|
||||
int tst_add_tl(msg_t *msg, msg_test_t *tst,
|
||||
tag_type_t tag, tag_value_t value, ...)
|
||||
{
|
||||
tagi_t const *t;
|
||||
ta_list ta;
|
||||
|
||||
ta_start(ta, tag, value);
|
||||
|
||||
for (t = ta_args(ta); t; t = tl_next(t)) {
|
||||
if (!(tag = t->t_tag) || !(value = t->t_value))
|
||||
continue;
|
||||
|
||||
if (TSTTAG_P(tag)) {
|
||||
msg_hclass_t *hc = (msg_hclass_t *)tag->tt_magic;
|
||||
msg_header_t *h = (msg_header_t *)value, **hh;
|
||||
|
||||
if (h == NULL)
|
||||
;
|
||||
else if (h == MSG_HEADER_NONE) { /* Remove header */
|
||||
hh = msg_hclass_offset(msg_mclass(msg), (msg_pub_t *)tst, hc);
|
||||
while (hh && *hh)
|
||||
msg_header_remove(msg, (msg_pub_t *)tst, *hh);
|
||||
} else if (msg_header_add_dup_as(msg, (msg_pub_t *)tst, hc, h) < 0)
|
||||
break;
|
||||
}
|
||||
else if (TSTTAG_STR_P(tag)) {
|
||||
msg_hclass_t *hc = (msg_hclass_t *)tag->tt_magic;
|
||||
char const *s = (char const *)value;
|
||||
if (s && msg_header_add_make(msg, (msg_pub_t *)tst, hc, s) < 0)
|
||||
break;
|
||||
}
|
||||
else if (tag == tsttag_header_str) {
|
||||
if (msg_header_add_str(msg, (msg_pub_t *)tst, (char const *)value) < 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ta_end(ta);
|
||||
|
||||
return t ? -1 : 0;
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TEST_CLASS_H
|
||||
/** Defined when <test_class.h> has been included. */
|
||||
#define TEST_CLASS_H
|
||||
|
||||
/**@ingroup test_msg
|
||||
* @file test_class.h
|
||||
* @brief Message and header classes for testing.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Thu Jun 29 15:58:06 2000 ppessi
|
||||
*/
|
||||
|
||||
#ifndef URL_H
|
||||
#include <sofia-sip/url.h>
|
||||
#endif
|
||||
#ifndef MSG_H
|
||||
#include <sofia-sip/msg.h>
|
||||
#endif
|
||||
#ifndef MSG_HEADER_H
|
||||
#include <sofia-sip/msg_header.h>
|
||||
#endif
|
||||
#ifndef MSG_MIME_H
|
||||
#include <sofia-sip/msg_mime.h>
|
||||
#endif
|
||||
#ifndef MSG_MCLASS_H
|
||||
#include <sofia-sip/msg_mclass.h>
|
||||
#endif
|
||||
|
||||
SOFIA_BEGIN_DECLS
|
||||
|
||||
#define MSG_TEST_PROTOCOL_TAG ((void *)(size_t)0xdeadbeef)
|
||||
|
||||
#define MSG_TEST_VERSION_CURRENT "msg/1.0"
|
||||
|
||||
extern msg_mclass_t const msg_test_mclass[1];
|
||||
|
||||
extern msg_href_t const msg_content_length_href[1];
|
||||
|
||||
typedef struct msg_request_s msg_request_t;
|
||||
typedef struct msg_status_s msg_status_t;
|
||||
|
||||
/** Request line. */
|
||||
struct msg_request_s {
|
||||
msg_common_t rq_common[1]; /**< Common fragment info */
|
||||
msg_header_t *rq_next; /**< Link to next header */
|
||||
char const *rq_method_name; /**< Method name */
|
||||
url_t rq_url[1]; /**< RequestURI */
|
||||
char const *rq_version; /**< Protocol version */
|
||||
};
|
||||
|
||||
/** Status line. */
|
||||
struct msg_status_s {
|
||||
msg_common_t st_common[1]; /**< Common fragment info */
|
||||
msg_header_t *st_next; /**< Link to next (dummy) */
|
||||
char const *st_version; /**< Protocol version */
|
||||
int st_status; /**< Status code */
|
||||
char const *st_phrase; /**< Status phrase */
|
||||
};
|
||||
|
||||
/** Message object for tests. */
|
||||
typedef struct msg_test_s {
|
||||
msg_common_t msg_common[1]; /**< For recursive inclusion */
|
||||
msg_pub_t *msg_next;
|
||||
void *msg_user; /**< User data */
|
||||
unsigned msg_size;
|
||||
unsigned msg_flags;
|
||||
msg_error_t *msg_error;
|
||||
|
||||
msg_request_t *msg_request;
|
||||
msg_status_t *msg_status;
|
||||
|
||||
/* === Headers start here */
|
||||
msg_content_type_t *msg_content_type; /**< Content-Type */
|
||||
msg_content_disposition_t *msg_content_disposition;
|
||||
/**< Content-Disposition */
|
||||
msg_content_location_t *msg_content_location; /**< Content-Location */
|
||||
msg_content_language_t *msg_content_language; /**< Content-Language */
|
||||
|
||||
msg_accept_t *msg_accept; /**< Accept */
|
||||
msg_accept_charset_t *msg_accept_charset; /**< Accept-Charset */
|
||||
msg_accept_encoding_t *msg_accept_encoding; /**< Accept-Encoding */
|
||||
msg_accept_language_t *msg_accept_language; /**< Accept-Language */
|
||||
msg_mime_version_t *msg_mime_version; /**< MIME-Version */
|
||||
msg_content_md5_t *msg_content_md5; /**< Content-MD5 */
|
||||
msg_content_encoding_t *msg_content_encoding;
|
||||
/**< Content-Encoding */
|
||||
msg_content_length_t *msg_content_length; /**< Content-Length */
|
||||
/* === Headers end here */
|
||||
|
||||
msg_unknown_t *msg_unknown;
|
||||
msg_separator_t *msg_separator;
|
||||
msg_payload_t *msg_payload;
|
||||
msg_multipart_t *msg_multipart;
|
||||
} msg_test_t;
|
||||
|
||||
union msg_test_u
|
||||
{
|
||||
msg_common_t sh_common[1];
|
||||
struct {
|
||||
msg_common_t shn_common;
|
||||
msg_header_t *shn_next;
|
||||
} sh_header_next[1];
|
||||
|
||||
msg_request_t sh_request[1];
|
||||
msg_status_t sh_status[1];
|
||||
msg_accept_t sh_accept[1];
|
||||
msg_accept_charset_t sh_accept_charset[1];
|
||||
msg_accept_encoding_t sh_accept_encoding[1];
|
||||
msg_accept_language_t sh_accept_language[1];
|
||||
msg_content_disposition_t sh_content_disposition[1];
|
||||
msg_content_encoding_t sh_content_encoding[1];
|
||||
msg_content_id_t sh_content_id[1];
|
||||
msg_content_md5_t sh_content_md5[1];
|
||||
msg_content_language_t sh_content_language[1];
|
||||
msg_content_length_t sh_content_length[1];
|
||||
msg_content_location_t sh_content_location[1];
|
||||
msg_content_type_t sh_content_type[1];
|
||||
msg_mime_version_t sh_mime_version[1];
|
||||
|
||||
msg_generic_t sh_generic[1];
|
||||
msg_numeric_t sh_numeric[1];
|
||||
msg_list_t sh_list[1];
|
||||
msg_auth_t sh_auth[1];
|
||||
msg_separator_t sh_separator[1];
|
||||
msg_payload_t sh_payload[1];
|
||||
msg_unknown_t sh_unknown[1];
|
||||
};
|
||||
|
||||
issize_t msg_test_extract_body(msg_t *, msg_pub_t *,
|
||||
char b[], isize_t bsiz, int eos);
|
||||
|
||||
static inline
|
||||
msg_test_t *msg_test_public(msg_t *msg)
|
||||
{
|
||||
return (msg_test_t *)msg_public(msg, MSG_TEST_PROTOCOL_TAG);
|
||||
}
|
||||
|
||||
SOFIA_END_DECLS
|
||||
|
||||
#endif /* !defined(TEST_CLASS_H) */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,359 @@
|
||||
/**-*- c -*-
|
||||
* @ingroup msg
|
||||
* @internal @file test_protos.h.in
|
||||
*
|
||||
* Template for "test_protos.h".
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TEST_PROTOS_H
|
||||
/** Defined when <test_protos.h> has been included. */
|
||||
#define TEST_PROTOS_H
|
||||
|
||||
/**@ingroup test_msg
|
||||
* @file test_protos.h
|
||||
*
|
||||
* Prototypes and macros for dummy testing protocol headers.
|
||||
*
|
||||
* #AUTO#
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*/
|
||||
|
||||
#include <sofia-sip/su_config.h>
|
||||
#include <sofia-sip/su_tag.h>
|
||||
#include <sofia-sip/su_tag_class.h>
|
||||
|
||||
#ifndef MSG_HEADER_H
|
||||
#include <sofia-sip/msg_header.h>
|
||||
#endif
|
||||
|
||||
#ifndef MSG_MIME_PROTOS_H
|
||||
#include <sofia-sip/msg_mime_protos.h>
|
||||
#endif
|
||||
|
||||
#ifndef TEST_CLASS_H
|
||||
#include <test_class.h>
|
||||
#endif
|
||||
|
||||
SOFIA_BEGIN_DECLS
|
||||
|
||||
/** Test if tag type marks a msg_test_t structure. @HIDE */
|
||||
#define TSTTAG_P(tt) ((tt)->tt_class == tsthdrtag_class)
|
||||
/** Test if tag type marks a TST header string. @HIDE */
|
||||
#define TSTTAG_STR_P(tt) ((tt)->tt_class == tststrtag_class)
|
||||
/** Test if tag type marks a TST header structure. @HIDE */
|
||||
#define TSTTAG_TST_P(tt) ((tt)->tt_class == tstmsgtag_class)
|
||||
|
||||
/** Test if tag item contains msg_test_t structure. @HIDE */
|
||||
#define TSTTAGI_P(t) (TSTTAG_P((t)->t_tag))
|
||||
/** Test if tag item contains a TST header string. @HIDE */
|
||||
#define TSTTAGI_STR_P(t) (TSTTAG_STR_P((t)->t_tag))
|
||||
/** Test if tag item contains a TST header structure. @HIDE */
|
||||
#define TSTTAGI_TST_P(t) (TSTTAG_TST_P((t)->t_tag))
|
||||
|
||||
/** Tag class for TST headers */
|
||||
extern tag_class_t tsthdrtag_class[1];
|
||||
/** Tag class for string values of TST headers */
|
||||
extern tag_class_t tststrtag_class[1];
|
||||
/** Tag class for TST message */
|
||||
extern tag_class_t tstmsgtag_class[1];
|
||||
|
||||
/**Tag list item for header string.
|
||||
*
|
||||
* The TSTTAG_HEADER_STR() macro is used to include a tag item containing a
|
||||
* header string in the tag list, e.g.,
|
||||
* @code
|
||||
* TSTTAG_HEADER_STR("Priority: urgent").
|
||||
* @endcode
|
||||
*
|
||||
* @param x pointer to a string, or NULL.
|
||||
*
|
||||
* @HIDE
|
||||
*/
|
||||
#define TSTTAG_HEADER(x) tsttag_header, tsttag_header_v((x))
|
||||
|
||||
/** Tag for header string */
|
||||
extern tag_typedef_t tsttag_header;
|
||||
|
||||
#define TSTTAG_HEADER_REF(x) tsttag_header_ref, tsttag_header_vr(&(x))
|
||||
extern tag_typedef_t tsttag_header_ref;
|
||||
|
||||
#if HAVE_INLINE
|
||||
static inline tag_value_t
|
||||
tsttag_header_v(msg_header_t const *v)
|
||||
{ return (tag_value_t)v; }
|
||||
static inline tag_value_t
|
||||
tsttag_header_vr(msg_header_t const **vp)
|
||||
{ return (tag_value_t)vp; }
|
||||
#else
|
||||
#define tsttag_header_v(v) (tag_value_t)(v)
|
||||
#define tsttag_header_vr(vp) (tag_value_t)(vp)
|
||||
#endif
|
||||
|
||||
/**Tag list item for header string.
|
||||
*
|
||||
* The TSTTAG_HEADER_STR() macro is used to include a tag item containing a
|
||||
* header string in the tag list.
|
||||
*
|
||||
* @param x pointer to a string, or NULL.
|
||||
*
|
||||
* @HIDE
|
||||
*/
|
||||
#define TSTTAG_HEADER_STR(x) tsttag_header_str, tag_str_v((x))
|
||||
|
||||
/** Tag for header string */
|
||||
extern tag_typedef_t tsttag_header_str;
|
||||
|
||||
#define TSTTAG_HEADER_STR_REF(x) tsttag_header_str_ref, tag_str_vr(&(x))
|
||||
extern tag_typedef_t tsttag_header_str_ref;
|
||||
|
||||
#if HAVE_INLINE
|
||||
static inline
|
||||
tag_value_t tsttag_tst_v(msg_test_t const *v) { return (tag_value_t)v; }
|
||||
static inline
|
||||
tag_value_t tsttag_tst_vr(msg_test_t const **vp) { return (tag_value_t)vp; }
|
||||
#else
|
||||
#define tsttag_tst_v(v) (tag_value_t)(v)
|
||||
#define tsttag_tst_vr(vp) (tag_value_t)(vp)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**@addtogroup test_msg_#xxxxxx#*//**@{*/
|
||||
|
||||
/** Parse a #xxxxxxx_xxxxxxx#. @internal */
|
||||
msg_parse_f msg_#xxxxxx#_d;
|
||||
|
||||
/** Print a #xxxxxxx_xxxxxxx#. @internal */
|
||||
msg_print_f msg_#xxxxxx#_e;
|
||||
|
||||
|
||||
/**Header class for #xxxxxxx_xxxxxxx#.
|
||||
*
|
||||
* The header class msg_#xxxxxx#_class defines how a
|
||||
* #xxxxxxx_xxxxxxx# is parsed and printed. It also
|
||||
* contains methods used by message parser and other functions
|
||||
* to manipulate the msg_#xxxxxx#_t header structure.
|
||||
*/
|
||||
extern msg_hclass_t msg_#xxxxxx#_class[];
|
||||
|
||||
/**Initializer for structure msg_#xxxxxx#_t.
|
||||
*
|
||||
* A static msg_#xxxxxx#_t structure must be initialized
|
||||
* with the MSG_#XXXXXX#_INIT() macro. For instance,
|
||||
* @code
|
||||
*
|
||||
* msg_#xxxxxx#_t msg_#xxxxxx# = MSG_#XXXXXX#_INIT;
|
||||
*
|
||||
* @endcode
|
||||
* @HI
|
||||
*/
|
||||
#define MSG_#XXXXXX#_INIT() MSG_HDR_INIT(#xxxxxx#)
|
||||
|
||||
/**Initialize a structure msg_#xxxxxx#_t.
|
||||
*
|
||||
* An msg_#xxxxxx#_t structure can be initialized with the
|
||||
* msg_#xxxxxx#_init() function/macro. For instance,
|
||||
* @code
|
||||
*
|
||||
* msg_#xxxxxx#_t msg_#xxxxxx#;
|
||||
*
|
||||
* msg_#xxxxxx#_init(&msg_#xxxxxx#);
|
||||
*
|
||||
* @endcode
|
||||
* @HI
|
||||
*/
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_init(msg_#xxxxxx#_t x[1])
|
||||
{
|
||||
return MSG_HEADER_INIT(x, msg_#xxxxxx#_class, sizeof(msg_#xxxxxx#_t));
|
||||
}
|
||||
#else
|
||||
#define msg_#xxxxxx#_init(x) \
|
||||
MSG_HEADER_INIT(x, msg_#xxxxxx#_class, sizeof(msg_#xxxxxx#_t))
|
||||
#endif
|
||||
|
||||
/**Test if header object is instance of msg_#xxxxxx#_t.
|
||||
*
|
||||
* The function msg_is_#xxxxxx#() returns true (nonzero) if
|
||||
* the header class is an instance of #xxxxxxx_xxxxxxx#
|
||||
* object and false (zero) otherwise.
|
||||
*
|
||||
* @param header pointer to the header structure to be tested
|
||||
*
|
||||
* @return
|
||||
* The function msg_is_x#xxxxxx#() returns true (nonzero) if
|
||||
* the header object is an instance of header #xxxxxx# and
|
||||
* false (zero) otherwise.
|
||||
*/
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline int msg_is_#xxxxxx#(msg_header_t const *header)
|
||||
{
|
||||
return header && header->sh_class->hc_hash == msg_#xxxxxx#_hash;
|
||||
}
|
||||
#else
|
||||
int msg_is_#xxxxxx#(msg_header_t const *header);
|
||||
#endif
|
||||
|
||||
#define msg_#xxxxxx#_p(h) msg_is_#xxxxxx#((h))
|
||||
|
||||
/**Duplicate (deep copy) @c msg_#xxxxxx#_t.
|
||||
*
|
||||
* The function msg_#xxxxxx#_dup() duplicates a header
|
||||
* structure @a hdr. If the header structure @a hdr
|
||||
* contains a reference (@c hdr->x_next) to a list of
|
||||
* headers, all the headers in the list are duplicated, too.
|
||||
*
|
||||
* @param home memory home used to allocate new structure
|
||||
* @param hdr header structure to be duplicated
|
||||
*
|
||||
* When duplicating, all parameter lists and non-constant
|
||||
* strings attached to the header are copied, too. The
|
||||
* function uses given memory @a home to allocate all the
|
||||
* memory areas used to copy the header.
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
*
|
||||
* #xxxxxx# = msg_#xxxxxx#_dup(home, tst->msg_#xxxxxx#);
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* @return
|
||||
* The function msg_#xxxxxx#_dup() returns a pointer to the
|
||||
* newly duplicated msg_#xxxxxx#_t header structure, or NULL
|
||||
* upon an error.
|
||||
*/
|
||||
msg_#xxxxxx#_t *msg_#xxxxxx#_dup(su_home_t *home, msg_#xxxxxx#_t const *hdr);
|
||||
|
||||
/**Copy a msg_#xxxxxx#_t header structure.
|
||||
*
|
||||
* The function msg_#xxxxxx#_copy() copies a header structure @a
|
||||
* hdr. If the header structure @a hdr contains a reference (@c
|
||||
* hdr->h_next) to a list of headers, all the headers in that
|
||||
* list are copied, too. The function uses given memory @a home
|
||||
* to allocate all the memory areas used to copy the header
|
||||
* structure @a hdr.
|
||||
*
|
||||
* @param home memory home used to allocate new structure
|
||||
* @param hdr pointer to the header structure to be duplicated
|
||||
*
|
||||
* When copying, only the header structure and parameter lists
|
||||
* attached to it are duplicated. The new header structure
|
||||
* retains all the references to the strings within the old @a
|
||||
* header, including the encoding of the old header, if present.
|
||||
*
|
||||
* @par Example
|
||||
* @code
|
||||
*
|
||||
* #xxxxxx# = msg_#xxxxxx#_copy(home, tst->msg_#xxxxxx#);
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* @return
|
||||
* The function msg_#xxxxxx#_copy() returns a pointer to
|
||||
* newly copied header structure, or NULL upon an error.
|
||||
*/
|
||||
msg_#xxxxxx#_t *msg_#xxxxxx#_copy(su_home_t *home,
|
||||
msg_#xxxxxx#_t const *hdr);
|
||||
|
||||
/**Make a header structure msg_#xxxxxx#_t.
|
||||
*
|
||||
* The function msg_#xxxxxx#_make() makes a new
|
||||
* msg_#xxxxxx#_t header structure. It allocates a new
|
||||
* header structure, and decodes the string @a s as the
|
||||
* value of the structure.
|
||||
*
|
||||
* @param home memory home used to allocate new header structure.
|
||||
* @param s string to be decoded as value of the new header structure
|
||||
*
|
||||
* @note This function is usually implemented as a macro calling
|
||||
* msg_header_make().
|
||||
*
|
||||
* @return
|
||||
* The function msg_#xxxxxx#_make() returns a pointer to
|
||||
* newly maked msg_#xxxxxx#_t header structure, or NULL upon
|
||||
* an error.
|
||||
*/
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_make(su_home_t *home, char const *s)
|
||||
{
|
||||
return (msg_#xxxxxx#_t *)msg_header_make(home, msg_#xxxxxx#_class, s);
|
||||
}
|
||||
#else
|
||||
msg_#xxxxxx#_t *msg_#xxxxxx#_make(su_home_t *home, char const *s);
|
||||
#endif
|
||||
|
||||
/**Make a #xxxxxxx_xxxxxxx# from formatting result.
|
||||
*
|
||||
* The function msg_#xxxxxx#_format() makes a new
|
||||
* #xxxxxxx_xxxxxxx# object using formatting result as its
|
||||
* value. The function first prints the arguments according to
|
||||
* the format @a fmt specified. Then it allocates a new header
|
||||
* structure, and uses the formatting result as the header
|
||||
* value.
|
||||
*
|
||||
* @param home memory home used to allocate new header structure.
|
||||
* @param fmt string used as a printf()-style format
|
||||
* @param ... argument list for format
|
||||
*
|
||||
* @note This function is usually implemented as a macro calling
|
||||
* msg_header_format().
|
||||
*
|
||||
* @return
|
||||
* The function msg_#xxxxxx#_format() returns a pointer to newly
|
||||
* makes header structure, or NULL upon an error.
|
||||
*
|
||||
* @HIDE
|
||||
*/
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline
|
||||
#endif
|
||||
msg_#xxxxxx#_t *msg_#xxxxxx#_format(su_home_t *home, char const *fmt, ...)
|
||||
__attribute__((__format__ (printf, 2, 3)));
|
||||
|
||||
#if SU_HAVE_INLINE
|
||||
su_inline msg_#xxxxxx#_t *msg_#xxxxxx#_format(su_home_t *home, char const *fmt, ...)
|
||||
{
|
||||
msg_header_t *h;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
h = msg_header_vformat(home, msg_#xxxxxx#_class, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return (msg_#xxxxxx#_t *)h;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
SOFIA_END_DECLS
|
||||
|
||||
#endif /* !defined(TEST_PROTOS_H) */
|
||||
@@ -0,0 +1,57 @@
|
||||
/**@ingroup test_msg
|
||||
* @IFILE test_table.c.in
|
||||
*
|
||||
* Template for <test_table.c>.
|
||||
*
|
||||
* @date Created: Wed Feb 21 11:01:45 2001 ppessi
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the Sofia-SIP package
|
||||
*
|
||||
* Copyright (C) 2005 Nokia Corporation.
|
||||
*
|
||||
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 test_msg
|
||||
*
|
||||
* @CFILE test_table.c
|
||||
* @brief Parser table used for testing.
|
||||
*
|
||||
* #AUTO#
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
* @date Created: Wed Jan 22 19:03:21 EET 2003 ppessi
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <test_class.h>
|
||||
#include <test_protos.h>
|
||||
#include <sofia-sip/msg_mime_protos.h>
|
||||
|
||||
#include <sofia-sip/msg_mclass.h>
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user