summaryrefslogtreecommitdiff
path: root/pjlib-util/include
diff options
context:
space:
mode:
authorDavid M. Lee <dlee@digium.com>2013-01-07 14:24:28 -0600
committerDavid M. Lee <dlee@digium.com>2013-01-07 14:24:28 -0600
commitf3ab456a17af1c89a6e3be4d20c5944853df1cb0 (patch)
treed00e1a332cd038a6d906a1ea0ac91e1a4458e617 /pjlib-util/include
Import pjproject-2.0.1
Diffstat (limited to 'pjlib-util/include')
-rw-r--r--pjlib-util/include/pjlib-util.h66
-rw-r--r--pjlib-util/include/pjlib-util/base64.h92
-rw-r--r--pjlib-util/include/pjlib-util/config.h274
-rw-r--r--pjlib-util/include/pjlib-util/crc32.h96
-rw-r--r--pjlib-util/include/pjlib-util/dns.h445
-rw-r--r--pjlib-util/include/pjlib-util/dns_server.h117
-rw-r--r--pjlib-util/include/pjlib-util/errno.h393
-rw-r--r--pjlib-util/include/pjlib-util/getopt.h146
-rw-r--r--pjlib-util/include/pjlib-util/hmac_md5.h109
-rw-r--r--pjlib-util/include/pjlib-util/hmac_sha1.h107
-rw-r--r--pjlib-util/include/pjlib-util/http_client.h494
-rw-r--r--pjlib-util/include/pjlib-util/md5.h74
-rw-r--r--pjlib-util/include/pjlib-util/pcap.h196
-rw-r--r--pjlib-util/include/pjlib-util/resolver.h460
-rw-r--r--pjlib-util/include/pjlib-util/scanner.h555
-rw-r--r--pjlib-util/include/pjlib-util/scanner_cis_bitwise.h97
-rw-r--r--pjlib-util/include/pjlib-util/scanner_cis_uint.h84
-rw-r--r--pjlib-util/include/pjlib-util/sha1.h80
-rw-r--r--pjlib-util/include/pjlib-util/srv_resolver.h215
-rw-r--r--pjlib-util/include/pjlib-util/string.h102
-rw-r--r--pjlib-util/include/pjlib-util/stun_simple.h209
-rw-r--r--pjlib-util/include/pjlib-util/types.h95
-rw-r--r--pjlib-util/include/pjlib-util/xml.h246
23 files changed, 4752 insertions, 0 deletions
diff --git a/pjlib-util/include/pjlib-util.h b/pjlib-util/include/pjlib-util.h
new file mode 100644
index 0000000..671bb07
--- /dev/null
+++ b/pjlib-util/include/pjlib-util.h
@@ -0,0 +1,66 @@
+/* $Id: pjlib-util.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_H__
+#define __PJLIB_UTIL_H__
+
+/**
+ * @file pjlib-util.h
+ * @brief pjlib-util.h
+ */
+
+/* Base */
+#include <pjlib-util/errno.h>
+#include <pjlib-util/types.h>
+
+/* Getopt */
+#include <pjlib-util/getopt.h>
+
+/* Crypto */
+#include <pjlib-util/base64.h>
+#include <pjlib-util/crc32.h>
+#include <pjlib-util/hmac_md5.h>
+#include <pjlib-util/hmac_sha1.h>
+#include <pjlib-util/md5.h>
+#include <pjlib-util/sha1.h>
+
+/* DNS and resolver */
+#include <pjlib-util/dns.h>
+#include <pjlib-util/resolver.h>
+#include <pjlib-util/srv_resolver.h>
+
+/* Simple DNS server */
+#include <pjlib-util/dns_server.h>
+
+/* Text scanner */
+#include <pjlib-util/scanner.h>
+
+/* XML */
+#include <pjlib-util/xml.h>
+
+/* Old STUN */
+#include <pjlib-util/stun_simple.h>
+
+/* PCAP */
+#include <pjlib-util/pcap.h>
+
+/* HTTP */
+#include <pjlib-util/http_client.h>
+
+#endif /* __PJLIB_UTIL_H__ */
diff --git a/pjlib-util/include/pjlib-util/base64.h b/pjlib-util/include/pjlib-util/base64.h
new file mode 100644
index 0000000..31ce0a4
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/base64.h
@@ -0,0 +1,92 @@
+/* $Id: base64.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_BASE64_H__
+#define __PJLIB_UTIL_BASE64_H__
+
+/**
+ * @file base64.h
+ * @brief Base64 encoding and decoding
+ */
+
+#include <pjlib-util/types.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJLIB_UTIL_BASE64 Base64 Encoding/Decoding
+ * @ingroup PJLIB_UTIL_ENCRYPTION
+ * @{
+ * This module implements base64 encoding and decoding.
+ */
+
+/**
+ * Helper macro to calculate the approximate length required for base256 to
+ * base64 conversion.
+ */
+#define PJ_BASE256_TO_BASE64_LEN(len) (len * 4 / 3 + 3)
+
+/**
+ * Helper macro to calculate the approximage length required for base64 to
+ * base256 conversion.
+ */
+#define PJ_BASE64_TO_BASE256_LEN(len) (len * 3 / 4)
+
+
+/**
+ * Encode a buffer into base64 encoding.
+ *
+ * @param input The input buffer.
+ * @param in_len Size of the input buffer.
+ * @param output Output buffer. Caller must allocate this buffer with
+ * the appropriate size.
+ * @param out_len On entry, it specifies the length of the output buffer.
+ * Upon return, this will be filled with the actual
+ * length of the output buffer.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pj_base64_encode(const pj_uint8_t *input, int in_len,
+ char *output, int *out_len);
+
+
+/**
+ * Decode base64 string.
+ *
+ * @param input Input string.
+ * @param out Buffer to store the output. Caller must allocate
+ * this buffer with the appropriate size.
+ * @param out_len On entry, it specifies the length of the output buffer.
+ * Upon return, this will be filled with the actual
+ * length of the output.
+ */
+PJ_DECL(pj_status_t) pj_base64_decode(const pj_str_t *input,
+ pj_uint8_t *out, int *out_len);
+
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+
+#endif /* __PJLIB_UTIL_BASE64_H__ */
+
diff --git a/pjlib-util/include/pjlib-util/config.h b/pjlib-util/include/pjlib-util/config.h
new file mode 100644
index 0000000..da0bb46
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/config.h
@@ -0,0 +1,274 @@
+/* $Id: config.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_CONFIG_H__
+#define __PJLIB_UTIL_CONFIG_H__
+
+
+/**
+ * @file config.h
+ * @brief Compile time settings
+ */
+
+/**
+ * @defgroup PJLIB_UTIL_CONFIG Configuration
+ * @ingroup PJLIB_UTIL_BASE
+ * @{
+ */
+
+
+/* **************************************************************************
+ * DNS CONFIGURATION
+ */
+
+/**
+ * Maximum number of IP addresses in DNS A response.
+ */
+#ifndef PJ_DNS_MAX_IP_IN_A_REC
+# define PJ_DNS_MAX_IP_IN_A_REC 8
+#endif
+
+
+/**
+ * Maximum server address entries per one SRV record
+ */
+#ifndef PJ_DNS_SRV_MAX_ADDR
+# define PJ_DNS_SRV_MAX_ADDR 8
+#endif
+
+
+/**
+ * This constant specifies the maximum names to keep in the temporary name
+ * table when performing name compression scheme when duplicating DNS packet
+ * (the #pj_dns_packet_dup() function).
+ *
+ * Generally name compression is desired, since it saves some memory (see
+ * PJ_DNS_RESOLVER_RES_BUF_SIZE setting). However it comes at the expense of
+ * a little processing overhead to perform name scanning and also a little
+ * bit more stack usage (8 bytes per entry on 32bit platform).
+ *
+ * Default: 16
+ */
+#ifndef PJ_DNS_MAX_NAMES_IN_NAMETABLE
+# define PJ_DNS_MAX_NAMES_IN_NAMETABLE 16
+#endif
+
+
+/* **************************************************************************
+ * RESOLVER CONFIGURATION
+ */
+
+
+/**
+ * Maximum numbers of DNS nameservers that can be configured in resolver.
+ */
+#ifndef PJ_DNS_RESOLVER_MAX_NS
+# define PJ_DNS_RESOLVER_MAX_NS 16
+#endif
+
+
+/**
+ * Default retransmission delay, in miliseconds. The combination of
+ * retransmission delay and count determines the query timeout.
+ *
+ * Default: 2000 (2 seconds, according to RFC 1035)
+ */
+#ifndef PJ_DNS_RESOLVER_QUERY_RETRANSMIT_DELAY
+# define PJ_DNS_RESOLVER_QUERY_RETRANSMIT_DELAY 2000
+#endif
+
+
+/**
+ * Maximum number of transmissions before timeout is declared for
+ * the query.
+ *
+ * Default: 5
+ */
+#ifndef PJ_DNS_RESOLVER_QUERY_RETRANSMIT_COUNT
+# define PJ_DNS_RESOLVER_QUERY_RETRANSMIT_COUNT 5
+#endif
+
+
+/**
+ * Maximum life-time of DNS response in the resolver response cache,
+ * in seconds. If the value is zero, then DNS response caching will be
+ * disabled.
+ *
+ * Default is 300 seconds (5 minutes).
+ *
+ * @see PJ_DNS_RESOLVER_INVALID_TTL
+ */
+#ifndef PJ_DNS_RESOLVER_MAX_TTL
+# define PJ_DNS_RESOLVER_MAX_TTL (5*60)
+#endif
+
+/**
+ * The life-time of invalid DNS response in the resolver response cache.
+ * An invalid DNS response is a response which RCODE is non-zero and
+ * response without any answer section. These responses can be put in
+ * the cache too to minimize message round-trip.
+ *
+ * Default: 60 (one minute).
+ *
+ * @see PJ_DNS_RESOLVER_MAX_TTL
+ */
+#ifndef PJ_DNS_RESOLVER_INVALID_TTL
+# define PJ_DNS_RESOLVER_INVALID_TTL 60
+#endif
+
+/**
+ * The interval on which nameservers which are known to be good to be
+ * probed again to determine whether they are still good. Note that
+ * this applies to both active nameserver (the one currently being used)
+ * and idle nameservers (good nameservers that are not currently selected).
+ * The probing to query the "goodness" of nameservers involves sending
+ * the same query to multiple servers, so it's probably not a good idea
+ * to send this probing too often.
+ *
+ * Default: 600 (ten minutes)
+ *
+ * @see PJ_DNS_RESOLVER_BAD_NS_TTL
+ */
+#ifndef PJ_DNS_RESOLVER_GOOD_NS_TTL
+# define PJ_DNS_RESOLVER_GOOD_NS_TTL (10*60)
+#endif
+
+/**
+ * The interval on which nameservers which known to be bad to be probed
+ * again to determine whether it is still bad.
+ *
+ * Default: 60 (one minute)
+ *
+ * @see PJ_DNS_RESOLVER_GOOD_NS_TTL
+ */
+#ifndef PJ_DNS_RESOLVER_BAD_NS_TTL
+# define PJ_DNS_RESOLVER_BAD_NS_TTL (1*60)
+#endif
+
+
+/**
+ * Maximum size of UDP packet. RFC 1035 states that maximum size of
+ * DNS packet carried over UDP is 512 bytes.
+ *
+ * Default: 512 byes
+ */
+#ifndef PJ_DNS_RESOLVER_MAX_UDP_SIZE
+# define PJ_DNS_RESOLVER_MAX_UDP_SIZE 512
+#endif
+
+
+/**
+ * Size of memory pool allocated for each individual DNS response cache.
+ * This value here should be more or less the same as maximum UDP packet
+ * size (PJ_DNS_RESOLVER_MAX_UDP_SIZE), since the DNS replicator function
+ * (#pj_dns_packet_dup()) is also capable of performing name compressions.
+ *
+ * Default: 512
+ */
+#ifndef PJ_DNS_RESOLVER_RES_BUF_SIZE
+# define PJ_DNS_RESOLVER_RES_BUF_SIZE 512
+#endif
+
+
+/**
+ * Size of temporary pool buffer for parsing DNS packets in resolver.
+ *
+ * default: 4000
+ */
+#ifndef PJ_DNS_RESOLVER_TMP_BUF_SIZE
+# define PJ_DNS_RESOLVER_TMP_BUF_SIZE 4000
+#endif
+
+
+/* **************************************************************************
+ * SCANNER CONFIGURATION
+ */
+
+
+/**
+ * Macro PJ_SCANNER_USE_BITWISE is defined and non-zero (by default yes)
+ * will enable the use of bitwise for character input specification (cis).
+ * This would save several kilobytes of .bss memory in the SIP parser.
+ */
+#ifndef PJ_SCANNER_USE_BITWISE
+# define PJ_SCANNER_USE_BITWISE 1
+#endif
+
+
+
+/* **************************************************************************
+ * STUN CLIENT CONFIGURATION
+ */
+
+/**
+ * Maximum number of attributes in the STUN packet (for the old STUN
+ * library).
+ *
+ * Default: 16
+ */
+#ifndef PJSTUN_MAX_ATTR
+# define PJSTUN_MAX_ATTR 16
+#endif
+
+
+/**
+ * Maximum number of attributes in the STUN packet (for the new STUN
+ * library).
+ *
+ * Default: 16
+ */
+#ifndef PJ_STUN_MAX_ATTR
+# define PJ_STUN_MAX_ATTR 16
+#endif
+
+
+/* **************************************************************************
+ * ENCRYPTION
+ */
+
+/**
+ * Specifies whether CRC32 algorithm should use the table based lookup table
+ * for faster calculation, at the expense of about 1KB table size on the
+ * executable. If zero, the CRC32 will use non-table based which is more than
+ * an order of magnitude slower.
+ *
+ * Default: 1
+ */
+#ifndef PJ_CRC32_HAS_TABLES
+# define PJ_CRC32_HAS_TABLES 1
+#endif
+
+
+/* **************************************************************************
+ * HTTP Client configuration
+ */
+/**
+ * Timeout value for HTTP request operation. The value is in ms.
+ * Default: 60000ms
+ */
+#ifndef PJ_HTTP_DEFAULT_TIMEOUT
+# define PJ_HTTP_DEFAULT_TIMEOUT (60000)
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* __PJLIB_UTIL_CONFIG_H__ */
+
diff --git a/pjlib-util/include/pjlib-util/crc32.h b/pjlib-util/include/pjlib-util/crc32.h
new file mode 100644
index 0000000..6203d1c
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/crc32.h
@@ -0,0 +1,96 @@
+/* $Id: crc32.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_CRC32_H__
+#define __PJLIB_UTIL_CRC32_H__
+
+/**
+ * @file crc32.h
+ * @brief CRC32 implementation
+ */
+
+#include <pjlib-util/types.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJLIB_UTIL_CRC32 CRC32 (Cyclic Redundancy Check)
+ * @ingroup PJLIB_UTIL_ENCRYPTION
+ * @{
+ * This implements CRC32 algorithm. See ITU-T V.42 for the formal
+ * specification.
+ */
+
+/** CRC32 context. */
+typedef struct pj_crc32_context
+{
+ pj_uint32_t crc_state; /**< Current state. */
+} pj_crc32_context;
+
+
+/**
+ * Initialize CRC32 context.
+ *
+ * @param ctx CRC32 context.
+ */
+PJ_DECL(void) pj_crc32_init(pj_crc32_context *ctx);
+
+/**
+ * Feed data incrementally to the CRC32 algorithm.
+ *
+ * @param ctx CRC32 context.
+ * @param data Input data.
+ * @param nbytes Length of the input data.
+ *
+ * @return The current CRC32 value.
+ */
+PJ_DECL(pj_uint32_t) pj_crc32_update(pj_crc32_context *ctx,
+ const pj_uint8_t *data,
+ pj_size_t nbytes);
+
+/**
+ * Finalize CRC32 calculation and retrieve the CRC32 value.
+ *
+ * @param ctx CRC32 context.
+ *
+ * @return The current CRC value.
+ */
+PJ_DECL(pj_uint32_t) pj_crc32_final(pj_crc32_context *ctx);
+
+/**
+ * Perform one-off CRC32 calculation to the specified data.
+ *
+ * @param data Input data.
+ * @param nbytes Length of input data.
+ *
+ * @return CRC value of the data.
+ */
+PJ_DECL(pj_uint32_t) pj_crc32_calc(const pj_uint8_t *data,
+ pj_size_t nbytes);
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+
+#endif /* __PJLIB_UTIL_CRC32_H__ */
+
diff --git a/pjlib-util/include/pjlib-util/dns.h b/pjlib-util/include/pjlib-util/dns.h
new file mode 100644
index 0000000..99c5bd8
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/dns.h
@@ -0,0 +1,445 @@
+/* $Id: dns.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_DNS_H__
+#define __PJLIB_UTIL_DNS_H__
+
+
+/**
+ * @file dns.h
+ * @brief Low level DNS message parsing and packetization.
+ */
+#include <pjlib-util/types.h>
+#include <pj/sock.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJ_DNS DNS and Asynchronous DNS Resolver
+ * @ingroup PJ_PROTOCOLS
+ */
+
+/**
+ * @defgroup PJ_DNS_PARSING Low-level DNS Message Parsing and Packetization
+ * @ingroup PJ_DNS
+ * @{
+ *
+ * This module provides low-level services to parse and packetize DNS queries
+ * and responses. The functions support building a DNS query packet and parse
+ * the data in the DNS response. This implementation conforms to the
+ * following specifications:
+ * - RFC 1035: DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION
+ * - RFC 1886: DNS Extensions to support IP version 6
+ *
+ * To create a DNS query packet, application should call #pj_dns_make_query()
+ * function, specifying the desired DNS query type, the name to be resolved,
+ * and the buffer where the DNS packet will be built into.
+ *
+ * When incoming DNS query or response packet arrives, application can use
+ * #pj_dns_parse_packet() to parse the TCP/UDP payload into parsed DNS packet
+ * structure.
+ *
+ * This module does not provide any networking functionalities to send or
+ * receive DNS packets. This functionality should be provided by higher layer
+ * modules such as @ref PJ_DNS_RESOLVER.
+ */
+
+enum
+{
+ PJ_DNS_CLASS_IN = 1 /**< DNS class IN. */
+};
+
+/**
+ * This enumeration describes standard DNS record types as described by
+ * RFC 1035, RFC 2782, and others.
+ */
+typedef enum pj_dns_type
+{
+ PJ_DNS_TYPE_A = 1, /**< Host address (A) record. */
+ PJ_DNS_TYPE_NS = 2, /**< Authoritative name server (NS) */
+ PJ_DNS_TYPE_MD = 3, /**< Mail destination (MD) record. */
+ PJ_DNS_TYPE_MF = 4, /**< Mail forwarder (MF) record. */
+ PJ_DNS_TYPE_CNAME = 5, /**< Canonical name (CNAME) record. */
+ PJ_DNS_TYPE_SOA = 6, /**< Marks start of zone authority. */
+ PJ_DNS_TYPE_MB = 7, /**< Mailbox domain name (MB). */
+ PJ_DNS_TYPE_MG = 8, /**< Mail group member (MG). */
+ PJ_DNS_TYPE_MR = 9, /**< Mail rename domain name. */
+ PJ_DNS_TYPE_NULL = 10, /**< NULL RR. */
+ PJ_DNS_TYPE_WKS = 11, /**< Well known service description */
+ PJ_DNS_TYPE_PTR = 12, /**< Domain name pointer. */
+ PJ_DNS_TYPE_HINFO = 13, /**< Host information. */
+ PJ_DNS_TYPE_MINFO = 14, /**< Mailbox or mail list information. */
+ PJ_DNS_TYPE_MX = 15, /**< Mail exchange record. */
+ PJ_DNS_TYPE_TXT = 16, /**< Text string. */
+ PJ_DNS_TYPE_RP = 17, /**< Responsible person. */
+ PJ_DNS_TYPE_AFSB = 18, /**< AFS cell database. */
+ PJ_DNS_TYPE_X25 = 19, /**< X.25 calling address. */
+ PJ_DNS_TYPE_ISDN = 20, /**< ISDN calling address. */
+ PJ_DNS_TYPE_RT = 21, /**< Router. */
+ PJ_DNS_TYPE_NSAP = 22, /**< NSAP address. */
+ PJ_DNS_TYPE_NSAP_PTR= 23, /**< NSAP reverse address. */
+ PJ_DNS_TYPE_SIG = 24, /**< Signature. */
+ PJ_DNS_TYPE_KEY = 25, /**< Key. */
+ PJ_DNS_TYPE_PX = 26, /**< X.400 mail mapping. */
+ PJ_DNS_TYPE_GPOS = 27, /**< Geographical position (withdrawn) */
+ PJ_DNS_TYPE_AAAA = 28, /**< IPv6 address. */
+ PJ_DNS_TYPE_LOC = 29, /**< Location. */
+ PJ_DNS_TYPE_NXT = 30, /**< Next valid name in the zone. */
+ PJ_DNS_TYPE_EID = 31, /**< Endpoint idenfitier. */
+ PJ_DNS_TYPE_NIMLOC = 32, /**< Nimrod locator. */
+ PJ_DNS_TYPE_SRV = 33, /**< Server selection (SRV) record. */
+ PJ_DNS_TYPE_ATMA = 34, /**< DNS ATM address record. */
+ PJ_DNS_TYPE_NAPTR = 35, /**< DNS Naming authority pointer record. */
+ PJ_DNS_TYPE_KX = 36, /**< DNS key exchange record. */
+ PJ_DNS_TYPE_CERT = 37, /**< DNS certificate record. */
+ PJ_DNS_TYPE_A6 = 38, /**< DNS IPv6 address (experimental) */
+ PJ_DNS_TYPE_DNAME = 39, /**< DNS non-terminal name redirection rec. */
+
+ PJ_DNS_TYPE_OPT = 41, /**< DNS options - contains EDNS metadata. */
+ PJ_DNS_TYPE_APL = 42, /**< DNS Address Prefix List (APL) record. */
+ PJ_DNS_TYPE_DS = 43, /**< DNS Delegation Signer (DS) */
+ PJ_DNS_TYPE_SSHFP = 44, /**< DNS SSH Key Fingerprint */
+ PJ_DNS_TYPE_IPSECKEY= 45, /**< DNS IPSEC Key. */
+ PJ_DNS_TYPE_RRSIG = 46, /**< DNS Resource Record signature. */
+ PJ_DNS_TYPE_NSEC = 47, /**< DNS Next Secure Name. */
+ PJ_DNS_TYPE_DNSKEY = 48 /**< DNSSEC Key. */
+} pj_dns_type;
+
+
+
+/**
+ * Standard DNS header, according to RFC 1035, which will be present in
+ * both DNS query and DNS response.
+ *
+ * Note that all values seen by application would be in
+ * host by order. The library would convert them to network
+ * byte order as necessary.
+ */
+typedef struct pj_dns_hdr
+{
+ pj_uint16_t id; /**< Transaction ID. */
+ pj_uint16_t flags; /**< Flags. */
+ pj_uint16_t qdcount; /**< Nb. of queries. */
+ pj_uint16_t anscount; /**< Nb. of res records */
+ pj_uint16_t nscount; /**< Nb. of NS records. */
+ pj_uint16_t arcount; /**< Nb. of additional records */
+} pj_dns_hdr;
+
+/** Create RCODE flag */
+#define PJ_DNS_SET_RCODE(c) ((pj_uint16_t)((c) & 0x0F))
+
+/** Create RA (Recursion Available) bit */
+#define PJ_DNS_SET_RA(on) ((pj_uint16_t)((on) << 7))
+
+/** Create RD (Recursion Desired) bit */
+#define PJ_DNS_SET_RD(on) ((pj_uint16_t)((on) << 8))
+
+/** Create TC (Truncated) bit */
+#define PJ_DNS_SET_TC(on) ((pj_uint16_t)((on) << 9))
+
+/** Create AA (Authoritative Answer) bit */
+#define PJ_DNS_SET_AA(on) ((pj_uint16_t)((on) << 10))
+
+/** Create four bits opcode */
+#define PJ_DNS_SET_OPCODE(o) ((pj_uint16_t)((o) << 11))
+
+/** Create query/response bit */
+#define PJ_DNS_SET_QR(on) ((pj_uint16_t)((on) << 15))
+
+
+/** Get RCODE value */
+#define PJ_DNS_GET_RCODE(val) (((val) & PJ_DNS_SET_RCODE(0x0F)) >> 0)
+
+/** Get RA bit */
+#define PJ_DNS_GET_RA(val) (((val) & PJ_DNS_SET_RA(1)) >> 7)
+
+/** Get RD bit */
+#define PJ_DNS_GET_RD(val) (((val) & PJ_DNS_SET_RD(1)) >> 8)
+
+/** Get TC bit */
+#define PJ_DNS_GET_TC(val) (((val) & PJ_DNS_SET_TC(1)) >> 9)
+
+/** Get AA bit */
+#define PJ_DNS_GET_AA(val) (((val) & PJ_DNS_SET_AA(1)) >> 10)
+
+/** Get OPCODE value */
+#define PJ_DNS_GET_OPCODE(val) (((val) & PJ_DNS_SET_OPCODE(0x0F)) >> 11)
+
+/** Get QR bit */
+#define PJ_DNS_GET_QR(val) (((val) & PJ_DNS_SET_QR(1)) >> 15)
+
+
+/**
+ * These constants describe DNS RCODEs. Application can fold these constants
+ * into PJLIB pj_status_t namespace by calling #PJ_STATUS_FROM_DNS_RCODE()
+ * macro.
+ */
+typedef enum pj_dns_rcode
+{
+ PJ_DNS_RCODE_FORMERR = 1, /**< Format error. */
+ PJ_DNS_RCODE_SERVFAIL = 2, /**< Server failure. */
+ PJ_DNS_RCODE_NXDOMAIN = 3, /**< Name Error. */
+ PJ_DNS_RCODE_NOTIMPL = 4, /**< Not Implemented. */
+ PJ_DNS_RCODE_REFUSED = 5, /**< Refused. */
+ PJ_DNS_RCODE_YXDOMAIN = 6, /**< The name exists. */
+ PJ_DNS_RCODE_YXRRSET = 7, /**< The RRset (name, type) exists. */
+ PJ_DNS_RCODE_NXRRSET = 8, /**< The RRset (name, type) doesn't exist*/
+ PJ_DNS_RCODE_NOTAUTH = 9, /**< Not authorized. */
+ PJ_DNS_RCODE_NOTZONE = 10 /**< The zone specified is not a zone. */
+
+} pj_dns_rcode;
+
+
+/**
+ * This structure describes a DNS query record.
+ */
+typedef struct pj_dns_parsed_query
+{
+ pj_str_t name; /**< The domain in the query. */
+ pj_uint16_t type; /**< Type of the query (pj_dns_type) */
+ pj_uint16_t dnsclass; /**< Network class (PJ_DNS_CLASS_IN=1) */
+} pj_dns_parsed_query;
+
+
+/**
+ * This structure describes a Resource Record parsed from the DNS packet.
+ * All integral values are in host byte order.
+ */
+typedef struct pj_dns_parsed_rr
+{
+ pj_str_t name; /**< The domain name which this rec pertains. */
+ pj_uint16_t type; /**< RR type code. */
+ pj_uint16_t dnsclass; /**< Class of data (PJ_DNS_CLASS_IN=1). */
+ pj_uint32_t ttl; /**< Time to live. */
+ pj_uint16_t rdlength; /**< Resource data length. */
+ void *data; /**< Pointer to the raw resource data, only
+ when the type is not known. If it is known,
+ the data will be put in rdata below. */
+
+ /** For resource types that are recognized/supported by this library,
+ * the parsed resource data will be placed in this rdata union.
+ */
+ union rdata
+ {
+ /** SRV Resource Data (PJ_DNS_TYPE_SRV, 33) */
+ struct srv {
+ pj_uint16_t prio; /**< Target priority (lower is higher). */
+ pj_uint16_t weight; /**< Weight/proportion */
+ pj_uint16_t port; /**< Port number of the service */
+ pj_str_t target; /**< Target name. */
+ } srv;
+
+ /** CNAME Resource Data (PJ_DNS_TYPE_CNAME, 5) */
+ struct cname {
+ pj_str_t name; /**< Primary canonical name for an alias. */
+ } cname;
+
+ /** NS Resource Data (PJ_DNS_TYPE_NS, 2) */
+ struct ns {
+ pj_str_t name; /**< Primary name server. */
+ } ns;
+
+ /** PTR Resource Data (PJ_DNS_TYPE_PTR, 12) */
+ struct ptr {
+ pj_str_t name; /**< PTR name. */
+ } ptr;
+
+ /** A Resource Data (PJ_DNS_TYPE_A, 1) */
+ struct a {
+ pj_in_addr ip_addr;/**< IPv4 address in network byte order. */
+ } a;
+
+ /** AAAA Resource Data (PJ_DNS_TYPE_AAAA, 28) */
+ struct aaaa {
+ pj_in6_addr ip_addr;/**< IPv6 address in network byte order. */
+ } aaaa;
+
+ } rdata;
+
+} pj_dns_parsed_rr;
+
+
+/**
+ * This structure describes the parsed repersentation of the raw DNS packet.
+ * Note that all integral values in the parsed packet are represented in
+ * host byte order.
+ */
+typedef struct pj_dns_parsed_packet
+{
+ pj_dns_hdr hdr; /**< Pointer to DNS hdr, in host byte order */
+ pj_dns_parsed_query *q; /**< Array of DNS queries. */
+ pj_dns_parsed_rr *ans; /**< Array of DNS RR answer. */
+ pj_dns_parsed_rr *ns; /**< Array of NS record in the answer. */
+ pj_dns_parsed_rr *arr; /**< Array of additional RR answer. */
+} pj_dns_parsed_packet;
+
+
+/**
+ * Option flags to be specified when calling #pj_dns_packet_dup() function.
+ * These flags can be combined with bitwise OR operation.
+ */
+enum pj_dns_dup_options
+{
+ PJ_DNS_NO_QD = 1, /**< Do not duplicate the query section. */
+ PJ_DNS_NO_ANS = 2, /**< Do not duplicate the answer section. */
+ PJ_DNS_NO_NS = 4, /**< Do not duplicate the NS section. */
+ PJ_DNS_NO_AR = 8 /**< Do not duplicate the additional rec section */
+};
+
+
+/**
+ * Create DNS query packet to resolve the specified names. This function
+ * can be used to build any types of DNS query, such as A record or DNS SRV
+ * record.
+ *
+ * Application specifies the type of record and the name to be queried,
+ * and the function will build the DNS query packet into the buffer
+ * specified. Once the packet is successfully built, application can send
+ * the packet via TCP or UDP connection.
+ *
+ * @param packet The buffer to put the DNS query packet.
+ * @param size On input, it specifies the size of the buffer.
+ * On output, it will be filled with the actual size of
+ * the DNS query packet.
+ * @param id DNS query ID to associate DNS response with the
+ * query.
+ * @param qtype DNS type of record to be queried (see #pj_dns_type).
+ * @param name Name to be queried from the DNS server.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pj_dns_make_query(void *packet,
+ unsigned *size,
+ pj_uint16_t id,
+ int qtype,
+ const pj_str_t *name);
+
+/**
+ * Parse raw DNS packet into parsed DNS packet structure. This function is
+ * able to parse few DNS resource records such as A record, PTR record,
+ * CNAME record, NS record, and SRV record.
+ *
+ * @param pool Pool to allocate memory for the parsed packet.
+ * @param packet Pointer to the DNS packet (the TCP/UDP payload of
+ * the raw packet).
+ * @param size The size of the DNS packet.
+ * @param p_res Pointer to store the resulting parsed packet.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pj_dns_parse_packet(pj_pool_t *pool,
+ const void *packet,
+ unsigned size,
+ pj_dns_parsed_packet **p_res);
+
+/**
+ * Duplicate DNS packet.
+ *
+ * @param pool The pool to allocate memory for the duplicated packet.
+ * @param p The DNS packet to be cloned.
+ * @param options Option flags, from pj_dns_dup_options.
+ * @param p_dst Pointer to store the cloned DNS packet.
+ */
+PJ_DECL(void) pj_dns_packet_dup(pj_pool_t *pool,
+ const pj_dns_parsed_packet*p,
+ unsigned options,
+ pj_dns_parsed_packet **p_dst);
+
+
+/**
+ * Utility function to get the type name string of the specified DNS type.
+ *
+ * @param type DNS type (see #pj_dns_type).
+ *
+ * @return String name of the type (e.g. "A", "SRV", etc.).
+ */
+PJ_DECL(const char *) pj_dns_get_type_name(int type);
+
+
+/**
+ * Initialize DNS record as DNS SRV record.
+ *
+ * @param rec The DNS resource record to be initialized as DNS
+ * SRV record.
+ * @param res_name Resource name.
+ * @param dnsclass DNS class.
+ * @param ttl Resource TTL value.
+ * @param prio DNS SRV priority.
+ * @param weight DNS SRV weight.
+ * @param port Target port.
+ * @param target Target name.
+ */
+PJ_DECL(void) pj_dns_init_srv_rr(pj_dns_parsed_rr *rec,
+ const pj_str_t *res_name,
+ unsigned dnsclass,
+ unsigned ttl,
+ unsigned prio,
+ unsigned weight,
+ unsigned port,
+ const pj_str_t *target);
+
+/**
+ * Initialize DNS record as DNS CNAME record.
+ *
+ * @param rec The DNS resource record to be initialized as DNS
+ * CNAME record.
+ * @param res_name Resource name.
+ * @param dnsclass DNS class.
+ * @param ttl Resource TTL value.
+ * @param name Host name.
+ */
+PJ_DECL(void) pj_dns_init_cname_rr(pj_dns_parsed_rr *rec,
+ const pj_str_t *res_name,
+ unsigned dnsclass,
+ unsigned ttl,
+ const pj_str_t *name);
+
+/**
+ * Initialize DNS record as DNS A record.
+ *
+ * @param rec The DNS resource record to be initialized as DNS
+ * A record.
+ * @param res_name Resource name.
+ * @param dnsclass DNS class.
+ * @param ttl Resource TTL value.
+ * @param ip_addr Host address.
+ */
+PJ_DECL(void) pj_dns_init_a_rr(pj_dns_parsed_rr *rec,
+ const pj_str_t *res_name,
+ unsigned dnsclass,
+ unsigned ttl,
+ const pj_in_addr *ip_addr);
+
+/**
+ * Dump DNS packet to standard log.
+ *
+ * @param res The DNS packet.
+ */
+PJ_DECL(void) pj_dns_dump_packet(const pj_dns_parsed_packet *res);
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+
+#endif /* __PJLIB_UTIL_DNS_H__ */
+
diff --git a/pjlib-util/include/pjlib-util/dns_server.h b/pjlib-util/include/pjlib-util/dns_server.h
new file mode 100644
index 0000000..aaf5f6f
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/dns_server.h
@@ -0,0 +1,117 @@
+/* $Id: dns_server.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_DNS_SERVER_H__
+#define __PJLIB_UTIL_DNS_SERVER_H__
+
+/**
+ * @file dns_server.h
+ * @brief Simple DNS server
+ */
+#include <pjlib-util/types.h>
+#include <pjlib-util/dns.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJ_DNS_SERVER Simple DNS Server
+ * @ingroup PJ_DNS
+ * @{
+ * This contains a simple but fully working DNS server implementation,
+ * mostly for testing purposes. It supports serving various DNS resource
+ * records such as SRV, CNAME, A, and AAAA.
+ */
+
+/**
+ * Opaque structure to hold DNS server instance.
+ */
+typedef struct pj_dns_server pj_dns_server;
+
+/**
+ * Create the DNS server instance. The instance will run immediately.
+ *
+ * @param pf The pool factory to create memory pools.
+ * @param ioqueue Ioqueue instance where the server socket will be
+ * registered to.
+ * @param af Address family of the server socket (valid values
+ * are pj_AF_INET() for IPv4 and pj_AF_INET6() for IPv6).
+ * @param port The UDP port to listen.
+ * @param flags Flags, currently must be zero.
+ * @param p_srv Pointer to receive the DNS server instance.
+ *
+ * @return PJ_SUCCESS if server has been created successfully,
+ * otherwise the function will return the appropriate
+ * error code.
+ */
+PJ_DECL(pj_status_t) pj_dns_server_create(pj_pool_factory *pf,
+ pj_ioqueue_t *ioqueue,
+ int af,
+ unsigned port,
+ unsigned flags,
+ pj_dns_server **p_srv);
+
+/**
+ * Destroy DNS server instance.
+ *
+ * @param srv The DNS server instance.
+ *
+ * @return PJ_SUCCESS on success or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pj_dns_server_destroy(pj_dns_server *srv);
+
+
+/**
+ * Add generic resource record entries to the server.
+ *
+ * @param srv The DNS server instance.
+ * @param count Number of records to be added.
+ * @param rr Array of records to be added.
+ *
+ * @return PJ_SUCCESS on success or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pj_dns_server_add_rec(pj_dns_server *srv,
+ unsigned count,
+ const pj_dns_parsed_rr rr[]);
+
+/**
+ * Remove the specified record from the server.
+ *
+ * @param srv The DNS server instance.
+ * @param dns_class The resource's DNS class. Valid value is PJ_DNS_CLASS_IN.
+ * @param type The resource type.
+ * @param name The resource name to be removed.
+ *
+ * @return PJ_SUCCESS on success or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pj_dns_server_del_rec(pj_dns_server *srv,
+ int dns_class,
+ pj_dns_type type,
+ const pj_str_t *name);
+
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+
+#endif /* __PJLIB_UTIL_DNS_SERVER_H__ */
+
diff --git a/pjlib-util/include/pjlib-util/errno.h b/pjlib-util/include/pjlib-util/errno.h
new file mode 100644
index 0000000..5f93bc8
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/errno.h
@@ -0,0 +1,393 @@
+/* $Id: errno.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_ERRNO_H__
+#define __PJLIB_UTIL_ERRNO_H__
+
+
+#include <pj/errno.h>
+
+/**
+ * @defgroup PJLIB_UTIL_ERROR Error Codes
+ * @ingroup PJLIB_UTIL_BASE
+ * @{
+ */
+
+/**
+ * Start of error code relative to PJ_ERRNO_START_USER.
+ * This value is 320000.
+ */
+#define PJLIB_UTIL_ERRNO_START (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*3)
+
+
+/************************************************************
+ * STUN ERROR
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * Unable to resolve STUN server
+ */
+#define PJLIB_UTIL_ESTUNRESOLVE (PJLIB_UTIL_ERRNO_START+1) /* 320001 */
+/**
+ * @hideinitializer
+ * Unknown STUN message type.
+ */
+#define PJLIB_UTIL_ESTUNINMSGTYPE (PJLIB_UTIL_ERRNO_START+2) /* 320002 */
+/**
+ * @hideinitializer
+ * Invalid STUN message length
+ */
+#define PJLIB_UTIL_ESTUNINMSGLEN (PJLIB_UTIL_ERRNO_START+3) /* 320003 */
+/**
+ * @hideinitializer
+ * Invalid STUN attribute length
+ */
+#define PJLIB_UTIL_ESTUNINATTRLEN (PJLIB_UTIL_ERRNO_START+4) /* 320004 */
+/**
+ * @hideinitializer
+ * Invalid STUN attribute type
+ */
+#define PJLIB_UTIL_ESTUNINATTRTYPE (PJLIB_UTIL_ERRNO_START+5) /* 320005 */
+/**
+ * @hideinitializer
+ * Invalid STUN server/socket index
+ */
+#define PJLIB_UTIL_ESTUNININDEX (PJLIB_UTIL_ERRNO_START+6) /* 320006 */
+/**
+ * @hideinitializer
+ * No STUN binding response in the message
+ */
+#define PJLIB_UTIL_ESTUNNOBINDRES (PJLIB_UTIL_ERRNO_START+7) /* 320007 */
+/**
+ * @hideinitializer
+ * Received STUN error attribute
+ */
+#define PJLIB_UTIL_ESTUNRECVERRATTR (PJLIB_UTIL_ERRNO_START+8) /* 320008 */
+/**
+ * @hideinitializer
+ * No STUN mapped address attribute
+ */
+#define PJLIB_UTIL_ESTUNNOMAP (PJLIB_UTIL_ERRNO_START+9) /* 320009 */
+/**
+ * @hideinitializer
+ * Received no response from STUN server
+ */
+#define PJLIB_UTIL_ESTUNNOTRESPOND (PJLIB_UTIL_ERRNO_START+10) /* 320010 */
+/**
+ * @hideinitializer
+ * Symetric NAT detected by STUN
+ */
+#define PJLIB_UTIL_ESTUNSYMMETRIC (PJLIB_UTIL_ERRNO_START+11) /* 320011 */
+/**
+ * @hideinitializer
+ * Invalid STUN magic value
+ */
+#define PJLIB_UTIL_ESTUNNOTMAGIC (PJLIB_UTIL_ERRNO_START+12) /* 320012 */
+/**
+ * @hideinitializer
+ * Invalid STUN fingerprint value
+ */
+#define PJLIB_UTIL_ESTUNFINGERPRINT (PJLIB_UTIL_ERRNO_START+13) /* 320013 */
+
+
+
+/************************************************************
+ * XML ERROR
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * General invalid XML message.
+ */
+#define PJLIB_UTIL_EINXML (PJLIB_UTIL_ERRNO_START+20) /* 320020 */
+
+
+
+/************************************************************
+ * DNS ERROR
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * DNS query packet buffer is too small.
+ * This error occurs when the user supplied buffer for creating DNS
+ * query (#pj_dns_make_query() function) is too small.
+ */
+#define PJLIB_UTIL_EDNSQRYTOOSMALL (PJLIB_UTIL_ERRNO_START+40) /* 320040 */
+/**
+ * @hideinitializer
+ * Invalid DNS packet length.
+ * This error occurs when the received DNS response packet does not
+ * match all the fields length.
+ */
+#define PJLIB_UTIL_EDNSINSIZE (PJLIB_UTIL_ERRNO_START+41) /* 320041 */
+/**
+ * @hideinitializer
+ * Invalid DNS class.
+ * This error occurs when the received DNS response contains network
+ * class other than IN (Internet).
+ */
+#define PJLIB_UTIL_EDNSINCLASS (PJLIB_UTIL_ERRNO_START+42) /* 320042 */
+/**
+ * @hideinitializer
+ * Invalid DNS name pointer.
+ * This error occurs when parsing the compressed names inside DNS
+ * response packet, when the name pointer points to an invalid address
+ * or the parsing has triggerred too much recursion.
+ */
+#define PJLIB_UTIL_EDNSINNAMEPTR (PJLIB_UTIL_ERRNO_START+43) /* 320043 */
+/**
+ * @hideinitializer
+ * Invalid DNS nameserver address. If hostname was specified for nameserver
+ * address, this error means that the function was unable to resolve
+ * the nameserver hostname.
+ */
+#define PJLIB_UTIL_EDNSINNSADDR (PJLIB_UTIL_ERRNO_START+44) /* 320044 */
+/**
+ * @hideinitializer
+ * No nameserver is in DNS resolver. No nameserver is configured in the
+ * resolver.
+ */
+#define PJLIB_UTIL_EDNSNONS (PJLIB_UTIL_ERRNO_START+45) /* 320045 */
+/**
+ * @hideinitializer
+ * No working DNS nameserver. All nameservers have been queried,
+ * but none was able to serve any DNS requests. These "bad" nameservers
+ * will be re-tested again for "goodness" after some period.
+ */
+#define PJLIB_UTIL_EDNSNOWORKINGNS (PJLIB_UTIL_ERRNO_START+46) /* 320046 */
+/**
+ * @hideinitializer
+ * No answer record in the DNS response.
+ */
+#define PJLIB_UTIL_EDNSNOANSWERREC (PJLIB_UTIL_ERRNO_START+47) /* 320047 */
+/**
+ * @hideinitializer
+ * Invalid DNS answer. This error is raised for example when the DNS
+ * answer does not have a query section, or the type of RR in the answer
+ * doesn't match the query.
+ */
+#define PJLIB_UTIL_EDNSINANSWER (PJLIB_UTIL_ERRNO_START+48) /* 320048 */
+
+
+/* DNS ERRORS MAPPED FROM RCODE: */
+
+/**
+ * Start of error code mapped from DNS RCODE
+ */
+#define PJLIB_UTIL_DNS_RCODE_START (PJLIB_UTIL_ERRNO_START+50) /* 320050 */
+
+/**
+ * Map DNS RCODE status into pj_status_t.
+ */
+#define PJ_STATUS_FROM_DNS_RCODE(rcode) (rcode==0 ? PJ_SUCCESS : \
+ PJLIB_UTIL_DNS_RCODE_START+rcode)
+/**
+ * @hideinitializer
+ * Format error - The name server was unable to interpret the query.
+ * This corresponds to DNS RCODE 1.
+ */
+#define PJLIB_UTIL_EDNS_FORMERR PJ_STATUS_FROM_DNS_RCODE(1) /* 320051 */
+/**
+ * @hideinitializer
+ * Server failure - The name server was unable to process this query due to a
+ * problem with the name server.
+ * This corresponds to DNS RCODE 2.
+ */
+#define PJLIB_UTIL_EDNS_SERVFAIL PJ_STATUS_FROM_DNS_RCODE(2) /* 320052 */
+/**
+ * @hideinitializer
+ * Name Error - Meaningful only for responses from an authoritative name
+ * server, this code signifies that the domain name referenced in the query
+ * does not exist.
+ * This corresponds to DNS RCODE 3.
+ */
+#define PJLIB_UTIL_EDNS_NXDOMAIN PJ_STATUS_FROM_DNS_RCODE(3) /* 320053 */
+/**
+ * @hideinitializer
+ * Not Implemented - The name server does not support the requested kind of
+ * query.
+ * This corresponds to DNS RCODE 4.
+ */
+#define PJLIB_UTIL_EDNS_NOTIMPL PJ_STATUS_FROM_DNS_RCODE(4) /* 320054 */
+/**
+ * @hideinitializer
+ * Refused - The name server refuses to perform the specified operation for
+ * policy reasons.
+ * This corresponds to DNS RCODE 5.
+ */
+#define PJLIB_UTIL_EDNS_REFUSED PJ_STATUS_FROM_DNS_RCODE(5) /* 320055 */
+/**
+ * @hideinitializer
+ * The name exists.
+ * This corresponds to DNS RCODE 6.
+ */
+#define PJLIB_UTIL_EDNS_YXDOMAIN PJ_STATUS_FROM_DNS_RCODE(6) /* 320056 */
+/**
+ * @hideinitializer
+ * The RRset (name, type) exists.
+ * This corresponds to DNS RCODE 7.
+ */
+#define PJLIB_UTIL_EDNS_YXRRSET PJ_STATUS_FROM_DNS_RCODE(7) /* 320057 */
+/**
+ * @hideinitializer
+ * The RRset (name, type) does not exist.
+ * This corresponds to DNS RCODE 8.
+ */
+#define PJLIB_UTIL_EDNS_NXRRSET PJ_STATUS_FROM_DNS_RCODE(8) /* 320058 */
+/**
+ * @hideinitializer
+ * The requestor is not authorized to perform this operation.
+ * This corresponds to DNS RCODE 9.
+ */
+#define PJLIB_UTIL_EDNS_NOTAUTH PJ_STATUS_FROM_DNS_RCODE(9) /* 320059 */
+/**
+ * @hideinitializer
+ * The zone specified is not a zone.
+ * This corresponds to DNS RCODE 10.
+ */
+#define PJLIB_UTIL_EDNS_NOTZONE PJ_STATUS_FROM_DNS_RCODE(10)/* 320060 */
+
+
+/************************************************************
+ * NEW STUN ERROR
+ ***********************************************************/
+/* Messaging errors */
+/**
+ * @hideinitializer
+ * Too many STUN attributes.
+ */
+#define PJLIB_UTIL_ESTUNTOOMANYATTR (PJLIB_UTIL_ERRNO_START+110)/* 320110 */
+/**
+ * @hideinitializer
+ * Unknown STUN attribute. This error happens when the decoder encounters
+ * mandatory attribute type which it doesn't understand.
+ */
+#define PJLIB_UTIL_ESTUNUNKNOWNATTR (PJLIB_UTIL_ERRNO_START+111)/* 320111 */
+/**
+ * @hideinitializer
+ * Invalid STUN socket address length.
+ */
+#define PJLIB_UTIL_ESTUNINADDRLEN (PJLIB_UTIL_ERRNO_START+112)/* 320112 */
+/**
+ * @hideinitializer
+ * STUN IPv6 attribute not supported
+ */
+#define PJLIB_UTIL_ESTUNIPV6NOTSUPP (PJLIB_UTIL_ERRNO_START+113)/* 320113 */
+/**
+ * @hideinitializer
+ * Expecting STUN response message.
+ */
+#define PJLIB_UTIL_ESTUNNOTRESPONSE (PJLIB_UTIL_ERRNO_START+114)/* 320114 */
+/**
+ * @hideinitializer
+ * STUN transaction ID mismatch.
+ */
+#define PJLIB_UTIL_ESTUNINVALIDID (PJLIB_UTIL_ERRNO_START+115)/* 320115 */
+/**
+ * @hideinitializer
+ * Unable to find handler for the request.
+ */
+#define PJLIB_UTIL_ESTUNNOHANDLER (PJLIB_UTIL_ERRNO_START+116)/* 320116 */
+/**
+ * @hideinitializer
+ * Found non-FINGERPRINT attribute after MESSAGE-INTEGRITY. This is not
+ * valid since MESSAGE-INTEGRITY MUST be the last attribute or the
+ * attribute right before FINGERPRINT before the message.
+ */
+#define PJLIB_UTIL_ESTUNMSGINTPOS (PJLIB_UTIL_ERRNO_START+118)/* 320118 */
+/**
+ * @hideinitializer
+ * Found attribute after FINGERPRINT. This is not valid since FINGERPRINT
+ * MUST be the last attribute in the message.
+ */
+#define PJLIB_UTIL_ESTUNFINGERPOS (PJLIB_UTIL_ERRNO_START+119)/* 320119 */
+/**
+ * @hideinitializer
+ * Missing STUN USERNAME attribute.
+ * When credential is included in the STUN message (MESSAGE-INTEGRITY is
+ * present), the USERNAME attribute must be present in the message.
+ */
+#define PJLIB_UTIL_ESTUNNOUSERNAME (PJLIB_UTIL_ERRNO_START+120)/* 320120 */
+/**
+ * @hideinitializer
+ * Unknown STUN username/credential.
+ */
+#define PJLIB_UTIL_ESTUNUSERNAME (PJLIB_UTIL_ERRNO_START+121)/* 320121 */
+/**
+ * @hideinitializer
+ * Missing/invalidSTUN MESSAGE-INTEGRITY attribute.
+ */
+#define PJLIB_UTIL_ESTUNMSGINT (PJLIB_UTIL_ERRNO_START+122)/* 320122 */
+/**
+ * @hideinitializer
+ * Found duplicate STUN attribute.
+ */
+#define PJLIB_UTIL_ESTUNDUPATTR (PJLIB_UTIL_ERRNO_START+123)/* 320123 */
+/**
+ * @hideinitializer
+ * Missing STUN REALM attribute.
+ */
+#define PJLIB_UTIL_ESTUNNOREALM (PJLIB_UTIL_ERRNO_START+124)/* 320124 */
+/**
+ * @hideinitializer
+ * Missing/stale STUN NONCE attribute value.
+ */
+#define PJLIB_UTIL_ESTUNNONCE (PJLIB_UTIL_ERRNO_START+125)/* 320125 */
+/**
+ * @hideinitializer
+ * STUN transaction terminates with failure.
+ */
+#define PJLIB_UTIL_ESTUNTSXFAILED (PJLIB_UTIL_ERRNO_START+126)/* 320126 */
+
+
+//#define PJ_STATUS_FROM_STUN_CODE(code) (PJLIB_UTIL_ERRNO_START+code)
+
+/************************************************************
+ * HTTP Client ERROR
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * Invalid URL format
+ */
+#define PJLIB_UTIL_EHTTPINURL (PJLIB_UTIL_ERRNO_START+151)/* 320151 */
+/**
+ * @hideinitializer
+ * Invalid port number
+ */
+#define PJLIB_UTIL_EHTTPINPORT (PJLIB_UTIL_ERRNO_START+152)/* 320152 */
+/**
+ * @hideinitializer
+ * Incomplete headers received
+ */
+#define PJLIB_UTIL_EHTTPINCHDR (PJLIB_UTIL_ERRNO_START+153)/* 320153 */
+/**
+ * @hideinitializer
+ * Insufficient buffer
+ */
+#define PJLIB_UTIL_EHTTPINSBUF (PJLIB_UTIL_ERRNO_START+154)/* 320154 */
+/**
+ * @hideinitializer
+ * Connection lost
+ */
+#define PJLIB_UTIL_EHTTPLOST (PJLIB_UTIL_ERRNO_START+155)/* 320155 */
+
+/**
+ * @}
+ */
+
+#endif /* __PJLIB_UTIL_ERRNO_H__ */
diff --git a/pjlib-util/include/pjlib-util/getopt.h b/pjlib-util/include/pjlib-util/getopt.h
new file mode 100644
index 0000000..3463b5c
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/getopt.h
@@ -0,0 +1,146 @@
+/* $Id: getopt.h 2037 2008-06-20 21:39:02Z bennylp $ */
+/* This file has now become GPL. */
+/* Declarations for pj_getopt.
+ Copyright (C) 1989,90,91,92,93,94,96,97,98 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef __PJ_GETOPT_H__
+#define __PJ_GETOPT_H__ 1
+
+/**
+ * @file getopt.h
+ * @brief Compile time settings
+ */
+
+/**
+ * @defgroup PJLIB_UTIL_GETOPT Getopt
+ * @ingroup PJLIB_TEXT
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `pj_getopt' to the caller.
+ When `pj_getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *pj_optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `pj_getopt'.
+
+ On entry to `pj_getopt', zero means this is the first call; initialize.
+
+ When `pj_getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `pj_optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int pj_optind;
+
+/* Set to an option character which was unrecognized. */
+
+extern int pj_optopt;
+
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to pj_getopt_long or pj_getopt_long_only is a vector
+ of `struct pj_getopt_option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, it points to a variable that is set
+ to the value given in the field `val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `pj_optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `pj_getopt'
+ returns the contents of the `val' field. */
+
+struct pj_getopt_option
+{
+ const char *name;
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct pj_getopt_option'. */
+
+# define no_argument 0
+# define required_argument 1
+# define optional_argument 2
+
+
+/* Get definitions and prototypes for functions to process the
+ arguments in ARGV (ARGC of them, minus the program name) for
+ options given in OPTS.
+
+ Return the option character from OPTS just read. Return -1 when
+ there are no more options. For unrecognized options, or options
+ missing arguments, `pj_optopt' is set to the option letter, and '?' is
+ returned.
+
+ The OPTS string is a list of characters which are recognized option
+ letters, optionally followed by colons, specifying that that letter
+ takes an argument, to be placed in `pj_optarg'.
+
+ If a letter in OPTS is followed by two colons, its argument is
+ optional. This behavior is specific to the GNU `pj_getopt'.
+
+ The argument `--' causes premature termination of argument
+ scanning, explicitly telling `pj_getopt' that there are no more
+ options.
+
+ If OPTS begins with `--', then non-option arguments are treated as
+ arguments to the option '\0'. This behavior is specific to the GNU
+ `pj_getopt'. */
+
+int pj_getopt (int argc, char *const *argv, const char *shortopts);
+
+int pj_getopt_long (int argc, char *const *argv, const char *options,
+ const struct pj_getopt_option *longopts, int *longind);
+int pj_getopt_long_only (int argc, char *const *argv,
+ const char *shortopts,
+ const struct pj_getopt_option *longopts, int *longind);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* pj_getopt.h */
+
diff --git a/pjlib-util/include/pjlib-util/hmac_md5.h b/pjlib-util/include/pjlib-util/hmac_md5.h
new file mode 100644
index 0000000..2ca9f1e
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/hmac_md5.h
@@ -0,0 +1,109 @@
+/* $Id: hmac_md5.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_HMAC_MD5_H__
+#define __PJLIB_UTIL_HMAC_MD5_H__
+
+/**
+ * @file hmac_md5.h
+ * @brief HMAC MD5 Message Authentication
+ */
+
+/**
+ * @defgroup PJLIB_UTIL_ENCRYPTION Encryption Algorithms
+ */
+
+#include <pj/types.h>
+#include <pjlib-util/md5.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJLIB_UTIL_HMAC_MD5 HMAC MD5 Message Authentication
+ * @ingroup PJLIB_UTIL_ENCRYPTION
+ * @{
+ *
+ * This module contains the implementation of HMAC: Keyed-Hashing
+ * for Message Authentication, as described in RFC 2104
+ */
+
+/**
+ * The HMAC-MD5 context used in the incremental HMAC calculation.
+ */
+typedef struct pj_hmac_md5_context
+{
+ pj_md5_context context; /**< MD5 context */
+ pj_uint8_t k_opad[64]; /**< opad xor-ed with key */
+} pj_hmac_md5_context;
+
+
+/**
+ * Calculate HMAC MD5 digest for the specified input and key.
+ *
+ * @param input Pointer to the input stream.
+ * @param input_len Length of input stream in bytes.
+ * @param key Pointer to the authentication key.
+ * @param key_len Length of the authentication key.
+ * @param digest Buffer to be filled with HMAC MD5 digest.
+ */
+PJ_DECL(void) pj_hmac_md5(const pj_uint8_t *input, unsigned input_len,
+ const pj_uint8_t *key, unsigned key_len,
+ pj_uint8_t digest[16]);
+
+
+/**
+ * Initiate HMAC-MD5 context for incremental hashing.
+ *
+ * @param hctx HMAC-MD5 context.
+ * @param key Pointer to the authentication key.
+ * @param key_len Length of the authentication key.
+ */
+PJ_DECL(void) pj_hmac_md5_init(pj_hmac_md5_context *hctx,
+ const pj_uint8_t *key, unsigned key_len);
+
+/**
+ * Append string to the message.
+ *
+ * @param hctx HMAC-MD5 context.
+ * @param input Pointer to the input stream.
+ * @param input_len Length of input stream in bytes.
+ */
+PJ_DECL(void) pj_hmac_md5_update(pj_hmac_md5_context *hctx,
+ const pj_uint8_t *input,
+ unsigned input_len);
+
+/**
+ * Finish the message and return the digest.
+ *
+ * @param hctx HMAC-MD5 context.
+ * @param digest Buffer to be filled with HMAC MD5 digest.
+ */
+PJ_DECL(void) pj_hmac_md5_final(pj_hmac_md5_context *hctx,
+ pj_uint8_t digest[16]);
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+
+#endif /* __PJLIB_UTIL_HMAC_MD5_H__ */
+
+
diff --git a/pjlib-util/include/pjlib-util/hmac_sha1.h b/pjlib-util/include/pjlib-util/hmac_sha1.h
new file mode 100644
index 0000000..539e465
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/hmac_sha1.h
@@ -0,0 +1,107 @@
+/* $Id: hmac_sha1.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_HMAC_SHA1_H__
+#define __PJLIB_UTIL_HMAC_SHA1_H__
+
+/**
+ * @file hmac_sha1.h
+ * @brief HMAC SHA1 Message Authentication
+ */
+
+#include <pj/types.h>
+#include <pjlib-util/sha1.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJLIB_UTIL_HMAC_SHA1 HMAC SHA1 Message Authentication
+ * @ingroup PJLIB_UTIL_ENCRYPTION
+ * @{
+ *
+ * This module contains the implementation of HMAC: Keyed-Hashing
+ * for Message Authentication, as described in RFC 2104.
+ */
+
+/**
+ * The HMAC-SHA1 context used in the incremental HMAC calculation.
+ */
+typedef struct pj_hmac_sha1_context
+{
+ pj_sha1_context context; /**< SHA1 context */
+ pj_uint8_t k_opad[64]; /**< opad xor-ed with key */
+} pj_hmac_sha1_context;
+
+
+/**
+ * Calculate HMAC-SHA1 digest for the specified input and key with this
+ * single function call.
+ *
+ * @param input Pointer to the input stream.
+ * @param input_len Length of input stream in bytes.
+ * @param key Pointer to the authentication key.
+ * @param key_len Length of the authentication key.
+ * @param digest Buffer to be filled with HMAC SHA1 digest.
+ */
+PJ_DECL(void) pj_hmac_sha1(const pj_uint8_t *input, unsigned input_len,
+ const pj_uint8_t *key, unsigned key_len,
+ pj_uint8_t digest[20]);
+
+
+/**
+ * Initiate HMAC-SHA1 context for incremental hashing.
+ *
+ * @param hctx HMAC-SHA1 context.
+ * @param key Pointer to the authentication key.
+ * @param key_len Length of the authentication key.
+ */
+PJ_DECL(void) pj_hmac_sha1_init(pj_hmac_sha1_context *hctx,
+ const pj_uint8_t *key, unsigned key_len);
+
+/**
+ * Append string to the message.
+ *
+ * @param hctx HMAC-SHA1 context.
+ * @param input Pointer to the input stream.
+ * @param input_len Length of input stream in bytes.
+ */
+PJ_DECL(void) pj_hmac_sha1_update(pj_hmac_sha1_context *hctx,
+ const pj_uint8_t *input,
+ unsigned input_len);
+
+/**
+ * Finish the message and return the digest.
+ *
+ * @param hctx HMAC-SHA1 context.
+ * @param digest Buffer to be filled with HMAC SHA1 digest.
+ */
+PJ_DECL(void) pj_hmac_sha1_final(pj_hmac_sha1_context *hctx,
+ pj_uint8_t digest[20]);
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+
+#endif /* __PJLIB_UTIL_HMAC_SHA1_H__ */
+
+
diff --git a/pjlib-util/include/pjlib-util/http_client.h b/pjlib-util/include/pjlib-util/http_client.h
new file mode 100644
index 0000000..38a8eff
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/http_client.h
@@ -0,0 +1,494 @@
+/* $Id: http_client.h 3841 2011-10-24 09:28:13Z ming $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_HTTP_CLIENT_H__
+#define __PJLIB_UTIL_HTTP_CLIENT_H__
+
+/**
+ * @file http_client.h
+ * @brief Simple HTTP Client
+ */
+#include <pj/activesock.h>
+#include <pjlib-util/types.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJ_HTTP_CLIENT Simple HTTP Client
+ * @ingroup PJ_PROTOCOLS
+ * @{
+ * This contains a simple HTTP client implementation.
+ * Some known limitations:
+ * - Does not support chunked Transfer-Encoding.
+ */
+
+/**
+ * This opaque structure describes the http request.
+ */
+typedef struct pj_http_req pj_http_req;
+
+/**
+ * Defines the maximum number of elements in a pj_http_headers
+ * structure.
+ */
+#define PJ_HTTP_HEADER_SIZE 32
+
+/**
+ * HTTP header representation.
+ */
+typedef struct pj_http_header_elmt
+{
+ pj_str_t name; /**< Header name */
+ pj_str_t value; /**< Header value */
+} pj_http_header_elmt;
+
+/**
+ * This structure describes http request/response headers.
+ * Application should call #pj_http_headers_add_elmt() to
+ * add a header field.
+ */
+typedef struct pj_http_headers
+{
+ /**< Number of header fields */
+ unsigned count;
+
+ /** Header elements/fields */
+ pj_http_header_elmt header[PJ_HTTP_HEADER_SIZE];
+} pj_http_headers;
+
+/**
+ * Structure to save HTTP authentication credential.
+ */
+typedef struct pj_http_auth_cred
+{
+ /**
+ * Specify specific authentication schemes to be responded. Valid values
+ * are "basic" and "digest". If this field is not set, any authentication
+ * schemes will be responded.
+ *
+ * Default is empty.
+ */
+ pj_str_t scheme;
+
+ /**
+ * Specify specific authentication realm to be responded. If this field
+ * is set, only 401/407 response with matching realm will be responded.
+ * If this field is not set, any realms will be responded.
+ *
+ * Default is empty.
+ */
+ pj_str_t realm;
+
+ /**
+ * Specify authentication username.
+ *
+ * Default is empty.
+ */
+ pj_str_t username;
+
+ /**
+ * The type of password in \a data field. Currently only 0 is
+ * supported, meaning the \a data contains plain-text password.
+ *
+ * Default is 0.
+ */
+ unsigned data_type;
+
+ /**
+ * Specify authentication password. The encoding of the password depends
+ * on the value of \a data_type field above.
+ *
+ * Default is empty.
+ */
+ pj_str_t data;
+
+} pj_http_auth_cred;
+
+
+/**
+ * Parameters that can be given during http request creation. Application
+ * must initialize this structure with #pj_http_req_param_default().
+ */
+typedef struct pj_http_req_param
+{
+ /**
+ * The address family of the URL.
+ * Default is pj_AF_INET().
+ */
+ int addr_family;
+
+ /**
+ * The HTTP request method.
+ * Default is GET.
+ */
+ pj_str_t method;
+
+ /**
+ * The HTTP protocol version ("1.0" or "1.1").
+ * Default is "1.0".
+ */
+ pj_str_t version;
+
+ /**
+ * HTTP request operation timeout.
+ * Default is PJ_HTTP_DEFAULT_TIMEOUT.
+ */
+ pj_time_val timeout;
+
+ /**
+ * User-defined data.
+ * Default is NULL.
+ */
+ void *user_data;
+
+ /**
+ * HTTP request headers.
+ * Default is empty.
+ */
+ pj_http_headers headers;
+
+ /**
+ * This structure describes the http request body. If application
+ * specifies the data to send, the data must remain valid until
+ * the HTTP request is sent. Alternatively, application can choose
+ * to specify total_size as the total data size to send instead
+ * while leaving the data NULL (and its size 0). In this case,
+ * HTTP request will then call on_send_data() callback once it is
+ * ready to send the request body. This will be useful if
+ * application does not wish to load the data into the buffer at
+ * once.
+ *
+ * Default is empty.
+ */
+ struct pj_http_reqdata
+ {
+ void *data; /**< Request body data */
+ pj_size_t size; /**< Request body size */
+ pj_size_t total_size; /**< If total_size > 0, data */
+ /**< will be provided later */
+ } reqdata;
+
+ /**
+ * Authentication credential needed to respond to 401/407 response.
+ */
+ pj_http_auth_cred auth_cred;
+
+ /**
+ * Optional source port range to use when binding the socket.
+ * This can be used if the source port needs to be within a certain range
+ * for instance due to strict firewall settings. The port used will be
+ * randomized within the range.
+ *
+ * Note that if authentication is configured, the authentication response
+ * will be a new transaction
+ *
+ * Default is 0 (The OS will select the source port automatically)
+ */
+ pj_uint16_t source_port_range_start;
+
+ /**
+ * Optional source port range to use when binding.
+ * The size of the port restriction range
+ *
+ * Default is 0 (The OS will select the source port automatically))
+ */
+ pj_uint16_t source_port_range_size;
+
+ /**
+ * Max number of retries if binding to a port fails.
+ * Note that this does not adress the scenario where a request times out
+ * or errors. This needs to be taken care of by the on_complete callback.
+ *
+ * Default is 3
+ */
+ pj_uint16_t max_retries;
+
+} pj_http_req_param;
+
+/**
+ * HTTP authentication challenge, parsed from WWW-Authenticate header.
+ */
+typedef struct pj_http_auth_chal
+{
+ pj_str_t scheme; /**< Auth scheme. */
+ pj_str_t realm; /**< Realm for the challenge. */
+ pj_str_t domain; /**< Domain. */
+ pj_str_t nonce; /**< Nonce challenge. */
+ pj_str_t opaque; /**< Opaque value. */
+ int stale; /**< Stale parameter. */
+ pj_str_t algorithm; /**< Algorithm parameter. */
+ pj_str_t qop; /**< Quality of protection. */
+} pj_http_auth_chal;
+
+/**
+ * This structure describes HTTP response.
+ */
+typedef struct pj_http_resp
+{
+ pj_str_t version; /**< HTTP version of the server */
+ pj_uint16_t status_code; /**< Status code of the request */
+ pj_str_t reason; /**< Reason phrase */
+ pj_http_headers headers; /**< Response headers */
+ pj_http_auth_chal auth_chal; /**< Parsed WWW-Authenticate header, if
+ any. */
+ pj_int32_t content_length; /**< The value of content-length header
+ field. -1 if not specified. */
+ void *data; /**< Data received */
+ pj_size_t size; /**< Data size */
+} pj_http_resp;
+
+/**
+ * This structure describes HTTP URL.
+ */
+typedef struct pj_http_url
+{
+ pj_str_t username; /**< Username part */
+ pj_str_t passwd; /**< Password part */
+ pj_str_t protocol; /**< Protocol used */
+ pj_str_t host; /**< Host name */
+ pj_uint16_t port; /**< Port number */
+ pj_str_t path; /**< Path */
+} pj_http_url;
+
+/**
+ * This structure describes the callbacks to be called by the HTTP request.
+ */
+typedef struct pj_http_req_callback
+{
+ /**
+ * This callback is called when a complete HTTP response header
+ * is received.
+ *
+ * @param http_req The http request.
+ * @param resp The response of the request.
+ */
+ void (*on_response)(pj_http_req *http_req, const pj_http_resp *resp);
+
+ /**
+ * This callback is called when the HTTP request is ready to send
+ * its request body. Application may wish to use this callback if
+ * it wishes to load the data at a later time or if it does not
+ * wish to load the whole data into memory. In order for this
+ * callback to be called, application MUST set http_req_param.total_size
+ * to a value greater than 0.
+ *
+ * @param http_req The http request.
+ * @param data Pointer to the data that will be sent. Application
+ * must set the pointer to the current data chunk/segment
+ * to be sent. Data must remain valid until the next
+ * on_send_data() callback or for the last segment,
+ * until it is sent.
+ * @param size Pointer to the data size that will be sent.
+ */
+ void (*on_send_data)(pj_http_req *http_req,
+ void **data, pj_size_t *size);
+
+ /**
+ * This callback is called when a segment of response body data
+ * arrives. If this callback is specified (i.e. not NULL), the
+ * on_complete() callback will be called with zero-length data
+ * (within the response parameter), hence the application must
+ * store and manage its own data buffer, otherwise the
+ * on_complete() callback will be called with the response
+ * parameter containing the complete data.
+ *
+ * @param http_req The http request.
+ * @param data The buffer containing the data.
+ * @param size The length of data in the buffer.
+ */
+ void (*on_data_read)(pj_http_req *http_req,
+ void *data, pj_size_t size);
+
+ /**
+ * This callback is called when the HTTP request is completed.
+ * If the callback on_data_read() is specified, the variable
+ * response->data will be set to NULL, otherwise it will
+ * contain the complete data. Response data is allocated from
+ * pj_http_req's internal memory pool so the data remain valid
+ * as long as pj_http_req is not destroyed and application does
+ * not start a new request.
+ *
+ * If no longer required, application may choose to destroy
+ * pj_http_req immediately by calling #pj_http_req_destroy() inside
+ * the callback.
+ *
+ * @param http_req The http request.
+ * @param status The status of the request operation. PJ_SUCCESS
+ * if the operation completed successfully
+ * (connection-wise). To check the server's
+ * status-code response to the HTTP request,
+ * application should check resp->status_code instead.
+ * @param resp The response of the corresponding request. If
+ * the status argument is non-PJ_SUCCESS, this
+ * argument will be set to NULL.
+ */
+ void (*on_complete)(pj_http_req *http_req,
+ pj_status_t status,
+ const pj_http_resp *resp);
+
+} pj_http_req_callback;
+
+
+/**
+ * Initialize the http request parameters with the default values.
+ *
+ * @param param The parameter to be initialized.
+ */
+PJ_DECL(void) pj_http_req_param_default(pj_http_req_param *param);
+
+/**
+ * Add a header element/field. Application MUST make sure that
+ * name and val pointer remains valid until the HTTP request is sent.
+ *
+ * @param headers The headers.
+ * @param name The header field name.
+ * @param value The header field value.
+ *
+ * @return PJ_SUCCESS if the operation has been successful,
+ * or the appropriate error code on failure.
+ */
+PJ_DECL(pj_status_t) pj_http_headers_add_elmt(pj_http_headers *headers,
+ pj_str_t *name,
+ pj_str_t *val);
+
+/**
+ * The same as #pj_http_headers_add_elmt() with char * as
+ * its parameters. Application MUST make sure that name and val pointer
+ * remains valid until the HTTP request is sent.
+ *
+ * @param headers The headers.
+ * @param name The header field name.
+ * @param value The header field value.
+ *
+ * @return PJ_SUCCESS if the operation has been successful,
+ * or the appropriate error code on failure.
+ */
+PJ_DECL(pj_status_t) pj_http_headers_add_elmt2(pj_http_headers *headers,
+ char *name, char *val);
+
+/**
+ * Parse a http URL into its components.
+ *
+ * @param url The URL to be parsed.
+ * @param hurl Pointer to receive the parsed result.
+ *
+ * @return PJ_SUCCESS if the operation has been successful,
+ * or the appropriate error code on failure.
+ */
+PJ_DECL(pj_status_t) pj_http_req_parse_url(const pj_str_t *url,
+ pj_http_url *hurl);
+
+/**
+ * Create the HTTP request.
+ *
+ * @param pool Pool to use. HTTP request will use the pool's factory
+ * to allocate its own memory pool.
+ * @param url HTTP URL request.
+ * @param timer The timer to use.
+ * @param ioqueue The ioqueue to use.
+ * @param param Optional parameters. When this parameter is not
+ * specifed (NULL), the default values will be used.
+ * @param hcb Pointer to structure containing application
+ * callbacks.
+ * @param http_req Pointer to receive the http request instance.
+ *
+ * @return PJ_SUCCESS if the operation has been successful,
+ * or the appropriate error code on failure.
+ */
+PJ_DECL(pj_status_t) pj_http_req_create(pj_pool_t *pool,
+ const pj_str_t *url,
+ pj_timer_heap_t *timer,
+ pj_ioqueue_t *ioqueue,
+ const pj_http_req_param *param,
+ const pj_http_req_callback *hcb,
+ pj_http_req **http_req);
+
+/**
+ * Set the timeout of the HTTP request operation. Note that if the
+ * HTTP request is currently running, the timeout will only affect
+ * subsequent request operations.
+ *
+ * @param http_req The http request.
+ * @param timeout Timeout value for HTTP request operation.
+ */
+PJ_DECL(void) pj_http_req_set_timeout(pj_http_req *http_req,
+ const pj_time_val* timeout);
+
+/**
+ * Starts an asynchronous HTTP request to the URL specified.
+ *
+ * @param http_req The http request.
+ *
+ * @return
+ * - PJ_SUCCESS if success
+ * - non-zero which indicates the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pj_http_req_start(pj_http_req *http_req);
+
+/**
+ * Cancel the asynchronous HTTP request.
+ *
+ * @param http_req The http request.
+ * @param notify If non-zero, the on_complete() callback will be
+ * called with status PJ_ECANCELLED to notify that
+ * the query has been cancelled.
+ *
+ * @return
+ * - PJ_SUCCESS if success
+ * - non-zero which indicates the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pj_http_req_cancel(pj_http_req *http_req,
+ pj_bool_t notify);
+
+/**
+ * Destroy the http request.
+ *
+ * @param http_req The http request to be destroyed.
+ *
+ * @return PJ_SUCCESS if success.
+ */
+PJ_DECL(pj_status_t) pj_http_req_destroy(pj_http_req *http_req);
+
+/**
+ * Find out whether the http request is running.
+ *
+ * @param http_req The http request.
+ *
+ * @return PJ_TRUE if a request is pending, or
+ * PJ_FALSE if idle
+ */
+PJ_DECL(pj_bool_t) pj_http_req_is_running(const pj_http_req *http_req);
+
+/**
+ * Retrieve the user data previously associated with this http
+ * request.
+ *
+ * @param http_req The http request.
+ *
+ * @return The user data.
+ */
+PJ_DECL(void *) pj_http_req_get_user_data(pj_http_req *http_req);
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+
+#endif /* __PJLIB_UTIL_HTTP_CLIENT_H__ */
diff --git a/pjlib-util/include/pjlib-util/md5.h b/pjlib-util/include/pjlib-util/md5.h
new file mode 100644
index 0000000..ed8aa5c
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/md5.h
@@ -0,0 +1,74 @@
+/* $Id: md5.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_MD5_H__
+#define __PJLIB_UTIL_MD5_H__
+
+/**
+ * @file md5.h
+ * @brief MD5 Functions
+ */
+
+#include <pj/types.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJLIB_UTIL_MD5 MD5
+ * @ingroup PJLIB_UTIL_ENCRYPTION
+ * @{
+ */
+
+
+/** MD5 context. */
+typedef struct pj_md5_context
+{
+ pj_uint32_t buf[4]; /**< buf */
+ pj_uint32_t bits[2]; /**< bits */
+ pj_uint8_t in[64]; /**< in */
+} pj_md5_context;
+
+/** Initialize the algorithm.
+ * @param pms MD5 context.
+ */
+PJ_DECL(void) pj_md5_init(pj_md5_context *pms);
+
+/** Append a string to the message.
+ * @param pms MD5 context.
+ * @param data Data.
+ * @param nbytes Length of data.
+ */
+PJ_DECL(void) pj_md5_update( pj_md5_context *pms,
+ const pj_uint8_t *data, unsigned nbytes);
+
+/** Finish the message and return the digest.
+ * @param pms MD5 context.
+ * @param digest 16 byte digest.
+ */
+PJ_DECL(void) pj_md5_final(pj_md5_context *pms, pj_uint8_t digest[16]);
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+
+#endif /* __PJLIB_UTIL_MD5_H__ */
diff --git a/pjlib-util/include/pjlib-util/pcap.h b/pjlib-util/include/pjlib-util/pcap.h
new file mode 100644
index 0000000..dd1be94
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/pcap.h
@@ -0,0 +1,196 @@
+/* $Id: pcap.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_PCAP_H__
+#define __PJLIB_UTIL_PCAP_H__
+
+/**
+ * @file pcap.h
+ * @brief Simple PCAP file reader
+ */
+
+#include <pj/types.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJ_PCAP Simple PCAP file reader
+ * @ingroup PJ_FILE_FMT
+ * @{
+ * This module describes simple utility to read PCAP file. It is not intended
+ * to support all PCAP features (that's what libpcap is for!), but it can
+ * be useful for example to playback or stream PCAP contents.
+ */
+
+/**
+ * Enumeration to describe supported data link types.
+ */
+typedef enum pj_pcap_link_type
+{
+ /** Ethernet data link */
+ PJ_PCAP_LINK_TYPE_ETH = 1
+
+} pj_pcap_link_type;
+
+
+/**
+ * Enumeration to describe supported protocol types.
+ */
+typedef enum pj_pcap_proto_type
+{
+ /** UDP protocol */
+ PJ_PCAP_PROTO_TYPE_UDP = 17
+
+} pj_pcap_proto_type;
+
+
+/**
+ * This describes UDP header, which may optionally be returned in
+ * #pj_pcap_read_udp() function. All fields are in network byte order.
+ */
+typedef struct pj_pcap_udp_hdr
+{
+ pj_uint16_t src_port; /**< Source port. */
+ pj_uint16_t dst_port; /**< Destination port */
+ pj_uint16_t len; /**< Length. */
+ pj_uint16_t csum; /**< Checksum. */
+} pj_pcap_udp_hdr;
+
+
+/**
+ * This structure describes the filter to be used when reading packets from
+ * a PCAP file. When a filter is configured, only packets matching all the
+ * filter specifications will be read from PCAP file.
+ */
+typedef struct pj_pcap_filter
+{
+ /**
+ * Select data link type, or zero to include any supported data links.
+ */
+ pj_pcap_link_type link;
+
+ /**
+ * Select protocol, or zero to include all supported protocols.
+ */
+ pj_pcap_proto_type proto;
+
+ /**
+ * Specify source IP address of the packets, or zero to include packets
+ * from any IP addresses. Note that IP address here must be in
+ * network byte order.
+ */
+ pj_uint32_t ip_src;
+
+ /**
+ * Specify destination IP address of the packets, or zero to include packets
+ * destined to any IP addresses. Note that IP address here must be in
+ * network byte order.
+ */
+ pj_uint32_t ip_dst;
+
+ /**
+ * Specify source port of the packets, or zero to include packets with
+ * any source port number. Note that the port number must be in network
+ * byte order.
+ */
+ pj_uint16_t src_port;
+
+ /**
+ * Specify destination port of the packets, or zero to include packets with
+ * any destination port number. Note that the port number must be in network
+ * byte order.
+ */
+ pj_uint16_t dst_port;
+
+} pj_pcap_filter;
+
+
+/** Opaque declaration for PCAP file */
+typedef struct pj_pcap_file pj_pcap_file;
+
+
+/**
+ * Initialize filter with default values. The default value is to allow
+ * any packets.
+ *
+ * @param filter Filter to be initialized.
+ */
+PJ_DECL(void) pj_pcap_filter_default(pj_pcap_filter *filter);
+
+/**
+ * Open PCAP file.
+ *
+ * @param pool Pool to allocate memory.
+ * @param path File/path name.
+ * @param p_file Pointer to receive PCAP file handle.
+ *
+ * @return PJ_SUCCESS if file can be opened successfully.
+ */
+PJ_DECL(pj_status_t) pj_pcap_open(pj_pool_t *pool,
+ const char *path,
+ pj_pcap_file **p_file);
+
+/**
+ * Close PCAP file.
+ *
+ * @param file PCAP file handle.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pj_pcap_close(pj_pcap_file *file);
+
+/**
+ * Configure filter for reading the file. When filter is configured,
+ * only packets matching all the filter settings will be returned.
+ *
+ * @param file PCAP file handle.
+ * @param filter The filter.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pj_pcap_set_filter(pj_pcap_file *file,
+ const pj_pcap_filter *filter);
+
+/**
+ * Read UDP payload from the next packet in the PCAP file. Optionally it
+ * can return the UDP header, if caller supplies it.
+ *
+ * @param file PCAP file handle.
+ * @param udp_hdr Optional buffer to receive UDP header.
+ * @param udp_payload Buffer to receive the UDP payload.
+ * @param udp_payload_size On input, specify the size of the buffer.
+ * On output, it will be filled with the actual size
+ * of the payload as read from the packet.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pj_pcap_read_udp(pj_pcap_file *file,
+ pj_pcap_udp_hdr *udp_hdr,
+ pj_uint8_t *udp_payload,
+ pj_size_t *udp_payload_size);
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+#endif /* __PJLIB_UTIL_PCAP_H__ */
+
diff --git a/pjlib-util/include/pjlib-util/resolver.h b/pjlib-util/include/pjlib-util/resolver.h
new file mode 100644
index 0000000..3fc1cba
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/resolver.h
@@ -0,0 +1,460 @@
+/* $Id: resolver.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_RESOLVER_H__
+#define __PJLIB_UTIL_RESOLVER_H__
+
+/**
+ * @file resolver.h
+ * @brief Asynchronous DNS resolver
+ */
+#include <pjlib-util/dns.h>
+
+
+PJ_BEGIN_DECL
+
+
+/**
+ * @defgroup PJ_DNS_RESOLVER DNS Asynchronous/Caching Resolution Engine
+ * @ingroup PJ_DNS
+ * @{
+ *
+ * This module manages the host/server resolution by performing asynchronous
+ * DNS queries and caching the results in the cache. It uses PJLIB-UTIL
+ * low-level DNS parsing functions (see @ref PJ_DNS) and currently supports
+ * several types of DNS resource records such as A record (typical query with
+ * gethostbyname()) and SRV record.
+ *
+ * \section PJ_DNS_RESOLVER_FEATURES Features
+ *
+ * \subsection PJ_DNS_RESOLVER_FEATURES_ASYNC Asynchronous Query and Query Aggregation
+ *
+ * The DNS queries are performed asychronously, with timeout setting
+ * configured on per resolver instance basis. Application can issue multiple
+ * asynchronous queries simultaneously. Subsequent queries to the same resource
+ * (name and DNS resource type) while existing query is still pending will be
+ * merged into one query, so that only one DNS request packet is issued.
+ *
+ * \subsection PJ_DNS_RESOLVER_FEATURES_RETRANSMISSION Query Retransmission
+ *
+ * Asynchronous query will be retransmitted if no response is received
+ * within the preconfigured time. Once maximum retransmission count is
+ * exceeded and no response is received, the query will time out and the
+ * callback will be called when error status.
+ *
+ * \subsection PJ_DNS_RESOLVER_FEATURES_CACHING Response Caching with TTL
+ *
+ * The resolver instance caches the results returned by nameservers, to
+ * enhance the performance by minimizing the message round-trip to the server.
+ * The TTL of the cached resposne is calculated from minimum TTL value found
+ * across all resource record (RR) TTL in the response and further more it can
+ * be limited to some preconfigured maximum TTL in the resolver.
+ *
+ * Response caching can be disabled by setting the maximum TTL value of the
+ * resolver to zero.
+ *
+ * \subsection PJ_DNS_RESOLVER_FEATURES_PARALLEL Parallel and Backup Name Servers
+ *
+ * When the resolver is configured with multiple nameservers, initially the
+ * queries will be issued to multiple name servers simultaneously to probe
+ * which servers are not active. Once the probing stage is done, subsequent
+ * queries will be directed to only one ACTIVE server which provides the best
+ * response time.
+ *
+ * Name servers are probed periodically to see which nameservers are active
+ * and which are down. This probing is done when a query is sent, thus no
+ * timer is needed to maintain this. Also probing will be done in parallel
+ * so that there would be no additional delay for the query.
+ *
+ *
+ * \subsection PJ_DNS_RESOLVER_FEATURES_REC Supported Resource Records
+ *
+ * The low-level DNS parsing utility (see @ref PJ_DNS) supports parsing of
+ * the following DNS resource records (RR):
+ * - DNS A record
+ * - DNS SRV record
+ * - DNS PTR record
+ * - DNS NS record
+ * - DNS CNAME record
+ *
+ * For other types of record, application can parse the raw resource
+ * record data (rdata) from the parsed DNS packet (#pj_dns_parsed_packet).
+ *
+ *
+ * \section PJ_DNS_RESOLVER_USING Using the Resolver
+ *
+ * To use the resolver, application first creates the resolver instance by
+ * calling #pj_dns_resolver_create(). If application already has its own
+ * timer and ioqueue instances, it can instruct the resolver to use these
+ * instances so that application does not need to poll the resolver
+ * periodically to process events. If application does not specify the
+ * timer and ioqueue instance for the resolver, an internal timer and
+ * ioqueue will be created by the resolver. And since the resolver does not
+ * create it's own thread, application MUST poll the resolver periodically
+ * by calling #pj_dns_resolver_handle_events() to allow events (network and
+ * timer) to be processed.
+ *
+ * Next, application MUST configure the nameservers to be used by the
+ * resolver, by calling #pj_dns_resolver_set_ns().
+ *
+ * Application performs asynchronous query by submitting the query with
+ * #pj_dns_resolver_start_query(). Once the query completes (either
+ * successfully or times out), the callback will be called.
+ *
+ * Application can cancel a pending query by calling #pj_dns_resolver_cancel_query().
+ *
+ * Resolver must be destroyed by calling #pj_dns_resolver_destroy() to
+ * release all resources back to the system.
+ *
+ *
+ * \section PJ_DNS_RESOLVER_LIMITATIONS Resolver Limitations
+ *
+ * Current implementation mainly suffers from a growing memory problem,
+ * which mainly is caused by the response caching. Although there is only
+ * one cache entry per {query, name} combination, these cache entry will
+ * never get deleted since there is no timer is created to invalidate these
+ * entries. So the more unique names being queried by application, there more
+ * enties will be created in the response cache.
+ *
+ * Note that a single response entry will occupy about 600-700 bytes of
+ * pool memory (the PJ_DNS_RESOLVER_RES_BUF_SIZE value plus internal
+ * structure).
+ *
+ * Application can work around this problem by doing one of these:
+ * - disable caching by setting PJ_DNS_RESOLVER_MAX_TTL and
+ * PJ_DNS_RESOLVER_INVALID_TTL to zero.
+ * - periodically query #pj_dns_resolver_get_cached_count() and destroy-
+ * recreate the resolver to recycle the memory used by the resolver.
+ *
+ * Note that future improvement may solve this problem by introducing
+ * expiration timer to the cached entries.
+ *
+ *
+ * \section PJ_DNS_RESOLVER_REFERENCE Reference
+ *
+ * The PJLIB-UTIL resolver was built from the information in the following
+ * standards:
+ * - <A HREF="http://www.faqs.org/rfcs/rfc1035.html">
+ * RFC 1035: "Domain names - implementation and specification"</A>
+ * - <A HREF="http://www.faqs.org/rfcs/rfc2782.html">
+ * RFC 2782: "A DNS RR for specifying the location of services (DNS SRV)"
+ * </A>
+ */
+
+
+
+/**
+ * Opaque data type for DNS resolver object.
+ */
+typedef struct pj_dns_resolver pj_dns_resolver;
+
+/**
+ * Opaque data type for asynchronous DNS query object.
+ */
+typedef struct pj_dns_async_query pj_dns_async_query;
+
+/**
+ * Type of asynchronous callback which will be called when the asynchronous
+ * query completes.
+ *
+ * @param user_data The user data set by application when creating the
+ * asynchronous query.
+ * @param status Status of the DNS resolution.
+ * @param response The response packet received from the server. This
+ * argument may be NULL when status is not PJ_SUCCESS.
+ */
+typedef void pj_dns_callback(void *user_data,
+ pj_status_t status,
+ pj_dns_parsed_packet *response);
+
+
+/**
+ * This structure describes resolver settings.
+ */
+typedef struct pj_dns_settings
+{
+ unsigned options; /**< Options flags. */
+ unsigned qretr_delay; /**< Query retransmit delay in msec. */
+ unsigned qretr_count; /**< Query maximum retransmission count. */
+ unsigned cache_max_ttl; /**< Maximum TTL for cached responses. If the
+ value is zero, caching is disabled. */
+ unsigned good_ns_ttl; /**< See #PJ_DNS_RESOLVER_GOOD_NS_TTL */
+ unsigned bad_ns_ttl; /**< See #PJ_DNS_RESOLVER_BAD_NS_TTL */
+} pj_dns_settings;
+
+
+/**
+ * This structure represents DNS A record, as the result of parsing
+ * DNS response packet using #pj_dns_parse_a_response().
+ */
+typedef struct pj_dns_a_record
+{
+ /** The target name being queried. */
+ pj_str_t name;
+
+ /** If target name corresponds to a CNAME entry, the alias contains
+ * the value of the CNAME entry, otherwise it will be empty.
+ */
+ pj_str_t alias;
+
+ /** Number of IP addresses. */
+ unsigned addr_count;
+
+ /** IP addresses of the host found in the response */
+ pj_in_addr addr[PJ_DNS_MAX_IP_IN_A_REC];
+
+ /** Internal buffer for hostname and alias. */
+ char buf_[128];
+
+} pj_dns_a_record;
+
+
+/**
+ * Set default values to the DNS settings.
+ *
+ * @param s The DNS settings to be initialized.
+ */
+PJ_DECL(void) pj_dns_settings_default(pj_dns_settings *s);
+
+
+/**
+ * Create DNS resolver instance. After the resolver is created, application
+ * MUST configure the nameservers with #pj_dns_resolver_set_ns().
+ *
+ * When creating the resolver, application may specify both timer heap
+ * and ioqueue instance, so that it doesn't need to poll the resolver
+ * periodically.
+ *
+ * @param pf Pool factory where the memory pool will be created from.
+ * @param name Optional resolver name to identify the instance in
+ * the log.
+ * @param options Optional options, must be zero for now.
+ * @param timer Optional timer heap instance to be used by the resolver.
+ * If timer heap is not specified, an internal timer will be
+ * created, and application would need to poll the resolver
+ * periodically.
+ * @param ioqueue Optional I/O Queue instance to be used by the resolver.
+ * If ioqueue is not specified, an internal one will be
+ * created, and application would need to poll the resolver
+ * periodically.
+ * @param p_resolver Pointer to receive the resolver instance.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code,
+ */
+PJ_DECL(pj_status_t) pj_dns_resolver_create(pj_pool_factory *pf,
+ const char *name,
+ unsigned options,
+ pj_timer_heap_t *timer,
+ pj_ioqueue_t *ioqueue,
+ pj_dns_resolver **p_resolver);
+
+
+/**
+ * Update the name servers for the DNS resolver. The name servers MUST be
+ * configured before any resolution can be done. The order of nameservers
+ * specifies their priority; the first name server will be tried first
+ * before the next in the list.
+ *
+ * @param resolver The resolver instance.
+ * @param count Number of name servers in the array.
+ * @param servers Array of name server IP addresses or hostnames. If
+ * hostname is specified, the hostname must be resolvable
+ * with pj_gethostbyname().
+ * @param ports Optional array of ports. If this argument is NULL,
+ * the nameserver will use default port.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code,
+ */
+PJ_DECL(pj_status_t) pj_dns_resolver_set_ns(pj_dns_resolver *resolver,
+ unsigned count,
+ const pj_str_t servers[],
+ const pj_uint16_t ports[]);
+
+
+/**
+ * Get the resolver current settings.
+ *
+ * @param resolver The resolver instance.
+ * @param st Buffer to be filled up with resolver settings.
+ *
+ * @return The query timeout setting, in seconds.
+ */
+PJ_DECL(pj_status_t) pj_dns_resolver_get_settings(pj_dns_resolver *resolver,
+ pj_dns_settings *st);
+
+
+/**
+ * Modify the resolver settings. Application should initialize the settings
+ * by retrieving current settings first before applying new settings, to
+ * ensure that all fields are initialized properly.
+ *
+ * @param resolver The resolver instance.
+ * @param st The resolver settings.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code,
+ */
+PJ_DECL(pj_status_t) pj_dns_resolver_set_settings(pj_dns_resolver *resolver,
+ const pj_dns_settings *st);
+
+
+/**
+ * Poll for events from the resolver. This function MUST be called
+ * periodically when the resolver is using it's own timer or ioqueue
+ * (in other words, when NULL is specified as either \a timer or
+ * \a ioqueue argument in #pj_dns_resolver_create()).
+ *
+ * @param resolver The resolver instance.
+ * @param timeout Maximum time to wait for event occurence. If this
+ * argument is NULL, this function will wait forever
+ * until events occur.
+ */
+PJ_DECL(void) pj_dns_resolver_handle_events(pj_dns_resolver *resolver,
+ const pj_time_val *timeout);
+
+
+/**
+ * Destroy DNS resolver instance.
+ *
+ * @param resolver The resolver object to be destryed
+ * @param notify If non-zero, all pending asynchronous queries will be
+ * cancelled and its callback will be called. If FALSE,
+ * then no callback will be called.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code,
+ */
+PJ_DECL(pj_status_t) pj_dns_resolver_destroy(pj_dns_resolver *resolver,
+ pj_bool_t notify);
+
+
+/**
+ * Create and start asynchronous DNS query for a single resource. Depending
+ * on whether response cache is available, this function will either start
+ * an asynchronous DNS query or call the callback immediately.
+ *
+ * If response is not available in the cache, an asynchronous query will be
+ * started, and callback will be called at some time later when the query
+ * completes. If \a p_query argument is not NULL, it will be filled with
+ * the asynchronous query object.
+ *
+ * If response is available in the cache, the callback will be called
+ * immediately before this function returns. In this case, if \a p_query
+ * argument is not NULL, the value will be set to NULL since no new query
+ * is started.
+ *
+ * @param resolver The resolver object.
+ * @param name The name to be resolved.
+ * @param type The type of resource (see #pj_dns_type constants).
+ * @param options Optional options, must be zero for now.
+ * @param cb Callback to be called when the query completes,
+ * either successfully or with failure.
+ * @param user_data Arbitrary user data to be associated with the query,
+ * and which will be given back in the callback.
+ * @param p_query Optional pointer to receive the query object, if one
+ * was started. If this pointer is specified, a NULL may
+ * be returned if response cache is available immediately.
+ *
+ * @return PJ_SUCCESS if either an asynchronous query has been
+ * started successfully or response cache is available and
+ * the user callback has been called.
+ */
+PJ_DECL(pj_status_t) pj_dns_resolver_start_query(pj_dns_resolver *resolver,
+ const pj_str_t *name,
+ int type,
+ unsigned options,
+ pj_dns_callback *cb,
+ void *user_data,
+ pj_dns_async_query **p_query);
+
+/**
+ * Cancel a pending query.
+ *
+ * @param query The pending asynchronous query to be cancelled.
+ * @param notify If non-zero, the callback will be called with failure
+ * status to notify that the query has been cancelled.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code,
+ */
+PJ_DECL(pj_status_t) pj_dns_resolver_cancel_query(pj_dns_async_query *query,
+ pj_bool_t notify);
+
+/**
+ * A utility function to parse a DNS response containing A records into
+ * DNS A record.
+ *
+ * @param pkt The DNS response packet.
+ * @param rec The structure to be initialized with the parsed
+ * DNS A record from the packet.
+ *
+ * @return PJ_SUCCESS if response can be parsed successfully.
+ */
+PJ_DECL(pj_status_t) pj_dns_parse_a_response(const pj_dns_parsed_packet *pkt,
+ pj_dns_a_record *rec);
+
+
+/**
+ * Put the specified DNS packet into DNS cache. This function is mainly used
+ * for testing the resolver, however it can also be used to inject entries
+ * into the resolver.
+ *
+ * The packet MUST contain either answer section or query section so that
+ * it can be indexed.
+ *
+ * @param resolver The resolver instance.
+ * @param pkt DNS packet to be added to the DNS cache. If the packet
+ * matches existing entry, it will update the entry.
+ * @param set_ttl If the value is PJ_FALSE, the entry will not expire
+ * (so use with care). Otherwise cache expiration will be
+ * calculated based on the TTL of the answeres.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pj_dns_resolver_add_entry(pj_dns_resolver *resolver,
+ const pj_dns_parsed_packet *pkt,
+ pj_bool_t set_ttl);
+
+/**
+ * Get the total number of response in the response cache.
+ *
+ * @param resolver The resolver instance.
+ *
+ * @return Current number of entries being stored in the response
+ * cache.
+ */
+PJ_DECL(unsigned) pj_dns_resolver_get_cached_count(pj_dns_resolver *resolver);
+
+
+/**
+ * Dump resolver state to the log.
+ *
+ * @param resolver The resolver instance.
+ * @param detail Will print detailed entries.
+ */
+PJ_DECL(void) pj_dns_resolver_dump(pj_dns_resolver *resolver,
+ pj_bool_t detail);
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+
+#endif /* __PJLIB_UTIL_RESOLVER_H__ */
+
diff --git a/pjlib-util/include/pjlib-util/scanner.h b/pjlib-util/include/pjlib-util/scanner.h
new file mode 100644
index 0000000..7bbeac5
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/scanner.h
@@ -0,0 +1,555 @@
+/* $Id: scanner.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJ_SCANNER_H__
+#define __PJ_SCANNER_H__
+
+/**
+ * @file scanner.h
+ * @brief Text Scanning.
+ */
+
+#include <pjlib-util/types.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJ_SCAN Fast Text Scanning
+ * @ingroup PJLIB_TEXT
+ * @brief Text scanning utility.
+ *
+ * This module describes a fast text scanning functions.
+ *
+ * @{
+ */
+#if defined(PJ_SCANNER_USE_BITWISE) && PJ_SCANNER_USE_BITWISE != 0
+# include <pjlib-util/scanner_cis_bitwise.h>
+#else
+# include <pjlib-util/scanner_cis_uint.h>
+#endif
+
+/**
+ * Initialize scanner input specification buffer.
+ *
+ * @param cs_buf The scanner character specification.
+ */
+PJ_DECL(void) pj_cis_buf_init(pj_cis_buf_t *cs_buf);
+
+/**
+ * Create a new input specification.
+ *
+ * @param cs_buf Specification buffer.
+ * @param cis Character input specification to be initialized.
+ *
+ * @return PJ_SUCCESS if new specification has been successfully
+ * created, or PJ_ETOOMANY if there are already too many
+ * specifications in the buffer.
+ */
+PJ_DECL(pj_status_t) pj_cis_init(pj_cis_buf_t *cs_buf, pj_cis_t *cis);
+
+/**
+ * Create a new input specification based on an existing specification.
+ *
+ * @param new_cis The new specification to be initialized.
+ * @param existing The existing specification, from which the input
+ * bitmask will be copied to the new specification.
+ *
+ * @return PJ_SUCCESS if new specification has been successfully
+ * created, or PJ_ETOOMANY if there are already too many
+ * specifications in the buffer.
+ */
+PJ_DECL(pj_status_t) pj_cis_dup(pj_cis_t *new_cis, pj_cis_t *existing);
+
+/**
+ * Add the characters in the specified range '[cstart, cend)' to the
+ * specification (the last character itself ('cend') is not added).
+ *
+ * @param cis The scanner character specification.
+ * @param cstart The first character in the range.
+ * @param cend The next character after the last character in the range.
+ */
+PJ_DECL(void) pj_cis_add_range( pj_cis_t *cis, int cstart, int cend);
+
+/**
+ * Add alphabetic characters to the specification.
+ *
+ * @param cis The scanner character specification.
+ */
+PJ_DECL(void) pj_cis_add_alpha( pj_cis_t *cis);
+
+/**
+ * Add numeric characters to the specification.
+ *
+ * @param cis The scanner character specification.
+ */
+PJ_DECL(void) pj_cis_add_num( pj_cis_t *cis);
+
+/**
+ * Add the characters in the string to the specification.
+ *
+ * @param cis The scanner character specification.
+ * @param str The string.
+ */
+PJ_DECL(void) pj_cis_add_str( pj_cis_t *cis, const char *str);
+
+/**
+ * Add specification from another specification.
+ *
+ * @param cis The specification is to be set.
+ * @param rhs The specification to be copied.
+ */
+PJ_DECL(void) pj_cis_add_cis( pj_cis_t *cis, const pj_cis_t *rhs);
+
+/**
+ * Delete characters in the specified range from the specification.
+ *
+ * @param cis The scanner character specification.
+ * @param cstart The first character in the range.
+ * @param cend The next character after the last character in the range.
+ */
+PJ_DECL(void) pj_cis_del_range( pj_cis_t *cis, int cstart, int cend);
+
+/**
+ * Delete characters in the specified string from the specification.
+ *
+ * @param cis The scanner character specification.
+ * @param str The string.
+ */
+PJ_DECL(void) pj_cis_del_str( pj_cis_t *cis, const char *str);
+
+/**
+ * Invert specification.
+ *
+ * @param cis The scanner character specification.
+ */
+PJ_DECL(void) pj_cis_invert( pj_cis_t *cis );
+
+/**
+ * Check whether the specified character belongs to the specification.
+ *
+ * @param cis The scanner character specification.
+ * @param c The character to check for matching.
+ *
+ * @return Non-zero if match (not necessarily one).
+ */
+PJ_INLINE(int) pj_cis_match( const pj_cis_t *cis, pj_uint8_t c )
+{
+ return PJ_CIS_ISSET(cis, c);
+}
+
+
+/**
+ * Flags for scanner.
+ */
+enum
+{
+ /** This flags specifies that the scanner should automatically skip
+ whitespaces
+ */
+ PJ_SCAN_AUTOSKIP_WS = 1,
+
+ /** This flags specifies that the scanner should automatically skip
+ SIP header continuation. This flag implies PJ_SCAN_AUTOSKIP_WS.
+ */
+ PJ_SCAN_AUTOSKIP_WS_HEADER = 3,
+
+ /** Auto-skip new lines.
+ */
+ PJ_SCAN_AUTOSKIP_NEWLINE = 4
+};
+
+
+/* Forward decl. */
+struct pj_scanner;
+
+
+/**
+ * The callback function type to be called by the scanner when it encounters
+ * syntax error.
+ *
+ * @param scanner The scanner instance that calls the callback .
+ */
+typedef void (*pj_syn_err_func_ptr)(struct pj_scanner *scanner);
+
+
+/**
+ * The text scanner structure.
+ */
+typedef struct pj_scanner
+{
+ char *begin; /**< Start of input buffer. */
+ char *end; /**< End of input buffer. */
+ char *curptr; /**< Current pointer. */
+ int line; /**< Current line. */
+ char *start_line; /**< Where current line starts. */
+ int skip_ws; /**< Skip whitespace flag. */
+ pj_syn_err_func_ptr callback; /**< Syntax error callback. */
+} pj_scanner;
+
+
+/**
+ * This structure can be used by application to store the state of the parser,
+ * so that the scanner state can be rollback to this state when necessary.
+ */
+typedef struct pj_scan_state
+{
+ char *curptr; /**< Current scanner's pointer. */
+ int line; /**< Current line. */
+ char *start_line; /**< Start of current line. */
+} pj_scan_state;
+
+
+/**
+ * Initialize the scanner. Note that the input string buffer must have
+ * length at least buflen+1 because the scanner will NULL terminate the
+ * string during initialization.
+ *
+ * @param scanner The scanner to be initialized.
+ * @param bufstart The input buffer to scan. Note that buffer[buflen] will be
+ * filled with NULL char until scanner is destroyed, so
+ * the actual buffer length must be at least buflen+1.
+ * @param buflen The length of the input buffer, which normally is
+ * strlen(bufstart).
+ * @param options Zero, or combination of PJ_SCAN_AUTOSKIP_WS or
+ * PJ_SCAN_AUTOSKIP_WS_HEADER
+ * @param callback Callback to be called when the scanner encounters syntax
+ * error condition.
+ */
+PJ_DECL(void) pj_scan_init( pj_scanner *scanner, char *bufstart, int buflen,
+ unsigned options,
+ pj_syn_err_func_ptr callback );
+
+
+/**
+ * Call this function when application has finished using the scanner.
+ *
+ * @param scanner The scanner.
+ */
+PJ_DECL(void) pj_scan_fini( pj_scanner *scanner );
+
+
+/**
+ * Determine whether the EOF condition for the scanner has been met.
+ *
+ * @param scanner The scanner.
+ *
+ * @return Non-zero if scanner is EOF.
+ */
+PJ_INLINE(int) pj_scan_is_eof( const pj_scanner *scanner)
+{
+ return scanner->curptr >= scanner->end;
+}
+
+
+/**
+ * Peek strings in current position according to parameter spec, and return
+ * the strings in parameter out. The current scanner position will not be
+ * moved. If the scanner is already in EOF state, syntax error callback will
+ * be called thrown.
+ *
+ * @param scanner The scanner.
+ * @param spec The spec to match input string.
+ * @param out String to store the result.
+ *
+ * @return the character right after the peek-ed position or zero if there's
+ * no more characters.
+ */
+PJ_DECL(int) pj_scan_peek( pj_scanner *scanner,
+ const pj_cis_t *spec, pj_str_t *out);
+
+
+/**
+ * Peek len characters in current position, and return them in out parameter.
+ * Note that whitespaces or newlines will be returned as it is, regardless
+ * of PJ_SCAN_AUTOSKIP_WS settings. If the character left is less than len,
+ * syntax error callback will be called.
+ *
+ * @param scanner The scanner.
+ * @param len Length to peek.
+ * @param out String to store the result.
+ *
+ * @return the character right after the peek-ed position or zero if there's
+ * no more characters.
+ */
+PJ_DECL(int) pj_scan_peek_n( pj_scanner *scanner,
+ pj_size_t len, pj_str_t *out);
+
+
+/**
+ * Peek strings in current position until spec is matched, and return
+ * the strings in parameter out. The current scanner position will not be
+ * moved. If the scanner is already in EOF state, syntax error callback will
+ * be called.
+ *
+ * @param scanner The scanner.
+ * @param spec The peeking will stop when the input match this spec.
+ * @param out String to store the result.
+ *
+ * @return the character right after the peek-ed position.
+ */
+PJ_DECL(int) pj_scan_peek_until( pj_scanner *scanner,
+ const pj_cis_t *spec,
+ pj_str_t *out);
+
+
+/**
+ * Get characters from the buffer according to the spec, and return them
+ * in out parameter. The scanner will attempt to get as many characters as
+ * possible as long as the spec matches. If the first character doesn't
+ * match the spec, or scanner is already in EOF when this function is called,
+ * an exception will be thrown.
+ *
+ * @param scanner The scanner.
+ * @param spec The spec to match input string.
+ * @param out String to store the result.
+ */
+PJ_DECL(void) pj_scan_get( pj_scanner *scanner,
+ const pj_cis_t *spec, pj_str_t *out);
+
+
+/**
+ * Just like #pj_scan_get(), but additionally performs unescaping when
+ * escaped ('%') character is found. The input spec MUST NOT contain the
+ * specification for '%' characted.
+ *
+ * @param scanner The scanner.
+ * @param spec The spec to match input string.
+ * @param out String to store the result.
+ */
+PJ_DECL(void) pj_scan_get_unescape( pj_scanner *scanner,
+ const pj_cis_t *spec, pj_str_t *out);
+
+
+/**
+ * Get characters between quotes. If current input doesn't match begin_quote,
+ * syntax error will be thrown. Note that the resulting string will contain
+ * the enclosing quote.
+ *
+ * @param scanner The scanner.
+ * @param begin_quote The character to begin the quote.
+ * @param end_quote The character to end the quote.
+ * @param out String to store the result.
+ */
+PJ_DECL(void) pj_scan_get_quote( pj_scanner *scanner,
+ int begin_quote, int end_quote,
+ pj_str_t *out);
+
+/**
+ * Get characters between quotes. If current input doesn't match begin_quote,
+ * syntax error will be thrown. Note that the resulting string will contain
+ * the enclosing quote.
+ *
+ * @param scanner The scanner.
+ * @param begin_quotes The character array to begin the quotes. For example,
+ * the two characters " and '.
+ * @param end_quotes The character array to end the quotes. The position
+ * found in the begin_quotes array will be used to match
+ * the end quotes. So if the begin_quotes was the array
+ * of "'< the end_quotes should be "'>. If begin_array
+ * matched the ' then the end_quotes will look for ' to
+ * match at the end.
+ * @param qsize The size of the begin_quotes and end_quotes arrays.
+ * @param out String to store the result.
+ */
+PJ_DECL(void) pj_scan_get_quotes(pj_scanner *scanner,
+ const char *begin_quotes,
+ const char *end_quotes, int qsize,
+ pj_str_t *out);
+
+
+/**
+ * Get N characters from the scanner.
+ *
+ * @param scanner The scanner.
+ * @param N Number of characters to get.
+ * @param out String to store the result.
+ */
+PJ_DECL(void) pj_scan_get_n( pj_scanner *scanner,
+ unsigned N, pj_str_t *out);
+
+
+/**
+ * Get one character from the scanner.
+ *
+ * @param scanner The scanner.
+ *
+ * @return The character.
+ */
+PJ_DECL(int) pj_scan_get_char( pj_scanner *scanner );
+
+
+/**
+ * Get characters from the scanner and move the scanner position until the
+ * current character matches the spec.
+ *
+ * @param scanner The scanner.
+ * @param spec Get until the input match this spec.
+ * @param out String to store the result.
+ */
+PJ_DECL(void) pj_scan_get_until( pj_scanner *scanner,
+ const pj_cis_t *spec, pj_str_t *out);
+
+
+/**
+ * Get characters from the scanner and move the scanner position until the
+ * current character matches until_char.
+ *
+ * @param scanner The scanner.
+ * @param until_char Get until the input match this character.
+ * @param out String to store the result.
+ */
+PJ_DECL(void) pj_scan_get_until_ch( pj_scanner *scanner,
+ int until_char, pj_str_t *out);
+
+
+/**
+ * Get characters from the scanner and move the scanner position until the
+ * current character matches until_char.
+ *
+ * @param scanner The scanner.
+ * @param until_spec Get until the input match any of these characters.
+ * @param out String to store the result.
+ */
+PJ_DECL(void) pj_scan_get_until_chr( pj_scanner *scanner,
+ const char *until_spec, pj_str_t *out);
+
+/**
+ * Advance the scanner N characters, and skip whitespace
+ * if necessary.
+ *
+ * @param scanner The scanner.
+ * @param N Number of characters to skip.
+ * @param skip Flag to specify whether whitespace should be skipped
+ * after skipping the characters.
+ */
+PJ_DECL(void) pj_scan_advance_n( pj_scanner *scanner,
+ unsigned N, pj_bool_t skip);
+
+
+/**
+ * Compare string in current position with the specified string.
+ *
+ * @param scanner The scanner.
+ * @param s The string to compare with.
+ * @param len Length of the string to compare.
+ *
+ * @return zero, <0, or >0 (just like strcmp()).
+ */
+PJ_DECL(int) pj_scan_strcmp( pj_scanner *scanner, const char *s, int len);
+
+
+/**
+ * Case-less string comparison of current position with the specified
+ * string.
+ *
+ * @param scanner The scanner.
+ * @param s The string to compare with.
+ * @param len Length of the string to compare with.
+ *
+ * @return zero, <0, or >0 (just like strcmp()).
+ */
+PJ_DECL(int) pj_scan_stricmp( pj_scanner *scanner, const char *s, int len);
+
+/**
+ * Perform case insensitive string comparison of string in current position,
+ * knowing that the string to compare only consists of alphanumeric
+ * characters.
+ *
+ * Note that unlike #pj_scan_stricmp, this function can only return zero or
+ * -1.
+ *
+ * @param scanner The scanner.
+ * @param s The string to compare with.
+ * @param len Length of the string to compare with.
+ *
+ * @return zero if equal or -1.
+ *
+ * @see strnicmp_alnum, pj_stricmp_alnum
+ */
+PJ_DECL(int) pj_scan_stricmp_alnum( pj_scanner *scanner, const char *s,
+ int len);
+
+
+/**
+ * Get a newline from the scanner. A newline is defined as '\\n', or '\\r', or
+ * "\\r\\n". If current input is not newline, syntax error will be thrown.
+ *
+ * @param scanner The scanner.
+ */
+PJ_DECL(void) pj_scan_get_newline( pj_scanner *scanner );
+
+
+/**
+ * Manually skip whitespaces according to flag that was specified when
+ * the scanner was initialized.
+ *
+ * @param scanner The scanner.
+ */
+PJ_DECL(void) pj_scan_skip_whitespace( pj_scanner *scanner );
+
+
+/**
+ * Skip current line.
+ *
+ * @param scanner The scanner.
+ */
+PJ_DECL(void) pj_scan_skip_line( pj_scanner *scanner );
+
+/**
+ * Save the full scanner state.
+ *
+ * @param scanner The scanner.
+ * @param state Variable to store scanner's state.
+ */
+PJ_DECL(void) pj_scan_save_state( const pj_scanner *scanner,
+ pj_scan_state *state);
+
+
+/**
+ * Restore the full scanner state.
+ * Note that this would not restore the string if application has modified
+ * it. This will only restore the scanner scanning position.
+ *
+ * @param scanner The scanner.
+ * @param state State of the scanner.
+ */
+PJ_DECL(void) pj_scan_restore_state( pj_scanner *scanner,
+ pj_scan_state *state);
+
+/**
+ * Get current column position.
+ *
+ * @param scanner The scanner.
+ *
+ * @return The column position.
+ */
+PJ_INLINE(int) pj_scan_get_col( const pj_scanner *scanner )
+{
+ return (int)(scanner->curptr - scanner->start_line);
+}
+
+/**
+ * @}
+ */
+
+
+PJ_END_DECL
+
+#endif
+
diff --git a/pjlib-util/include/pjlib-util/scanner_cis_bitwise.h b/pjlib-util/include/pjlib-util/scanner_cis_bitwise.h
new file mode 100644
index 0000000..ef0c7ff
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/scanner_cis_bitwise.h
@@ -0,0 +1,97 @@
+/* $Id: scanner_cis_bitwise.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_SCANNER_CIS_BIT_H__
+#define __PJLIB_UTIL_SCANNER_CIS_BIT_H__
+
+#include <pj/types.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * This describes the type of individual character specification in
+ * #pj_cis_buf_t. Basicly the number of bits here
+ */
+#ifndef PJ_CIS_ELEM_TYPE
+# define PJ_CIS_ELEM_TYPE pj_uint32_t
+#endif
+
+/**
+ * This describes the type of individual character specification in
+ * #pj_cis_buf_t.
+ */
+typedef PJ_CIS_ELEM_TYPE pj_cis_elem_t;
+
+/**
+ * Maximum number of input specification in a buffer.
+ * Effectively this means the number of bits in pj_cis_elem_t.
+ */
+#define PJ_CIS_MAX_INDEX (sizeof(pj_cis_elem_t) << 3)
+
+/**
+ * The scanner input specification buffer.
+ */
+typedef struct pj_cis_buf_t
+{
+ pj_cis_elem_t cis_buf[256]; /**< Must be 256 (not 128)! */
+ pj_cis_elem_t use_mask; /**< To keep used indexes. */
+} pj_cis_buf_t;
+
+/**
+ * Character input specification.
+ */
+typedef struct pj_cis_t
+{
+ pj_cis_elem_t *cis_buf; /**< Pointer to buffer. */
+ int cis_id; /**< Id. */
+} pj_cis_t;
+
+
+/**
+ * Set the membership of the specified character.
+ * Note that this is a macro, and arguments may be evaluated more than once.
+ *
+ * @param cis Pointer to character input specification.
+ * @param c The character.
+ */
+#define PJ_CIS_SET(cis,c) ((cis)->cis_buf[(int)(c)] |= (1 << (cis)->cis_id))
+
+/**
+ * Remove the membership of the specified character.
+ * Note that this is a macro, and arguments may be evaluated more than once.
+ *
+ * @param cis Pointer to character input specification.
+ * @param c The character to be removed from the membership.
+ */
+#define PJ_CIS_CLR(cis,c) ((cis)->cis_buf[(int)c] &= ~(1 << (cis)->cis_id))
+
+/**
+ * Check the membership of the specified character.
+ * Note that this is a macro, and arguments may be evaluated more than once.
+ *
+ * @param cis Pointer to character input specification.
+ * @param c The character.
+ */
+#define PJ_CIS_ISSET(cis,c) ((cis)->cis_buf[(int)c] & (1 << (cis)->cis_id))
+
+
+
+PJ_END_DECL
+
+#endif /* __PJLIB_UTIL_SCANNER_CIS_BIT_H__ */
diff --git a/pjlib-util/include/pjlib-util/scanner_cis_uint.h b/pjlib-util/include/pjlib-util/scanner_cis_uint.h
new file mode 100644
index 0000000..0cde7c7
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/scanner_cis_uint.h
@@ -0,0 +1,84 @@
+/* $Id: scanner_cis_uint.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_SCANNER_CIS_BIT_H__
+#define __PJLIB_UTIL_SCANNER_CIS_BIT_H__
+
+#include <pj/types.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * This describes the type of individual character specification in
+ * #pj_cis_buf_t. Basicly the number of bits here
+ */
+#ifndef PJ_CIS_ELEM_TYPE
+# define PJ_CIS_ELEM_TYPE int
+#endif
+
+/**
+ * This describes the type of individual character specification in
+ * #pj_cis_buf_t.
+ */
+typedef PJ_CIS_ELEM_TYPE pj_cis_elem_t;
+
+/** pj_cis_buf_t is not used when uint back-end is used. */
+typedef int pj_cis_buf_t;
+
+/**
+ * Character input specification.
+ */
+typedef struct pj_cis_t
+{
+ PJ_CIS_ELEM_TYPE cis_buf[256]; /**< Internal buffer. */
+} pj_cis_t;
+
+
+/**
+ * Set the membership of the specified character.
+ * Note that this is a macro, and arguments may be evaluated more than once.
+ *
+ * @param cis Pointer to character input specification.
+ * @param c The character.
+ */
+#define PJ_CIS_SET(cis,c) ((cis)->cis_buf[(int)(c)] = 1)
+
+/**
+ * Remove the membership of the specified character.
+ * Note that this is a macro, and arguments may be evaluated more than once.
+ *
+ * @param cis Pointer to character input specification.
+ * @param c The character to be removed from the membership.
+ */
+#define PJ_CIS_CLR(cis,c) ((cis)->cis_buf[(int)c] = 0)
+
+/**
+ * Check the membership of the specified character.
+ * Note that this is a macro, and arguments may be evaluated more than once.
+ *
+ * @param cis Pointer to character input specification.
+ * @param c The character.
+ */
+#define PJ_CIS_ISSET(cis,c) ((cis)->cis_buf[(int)c])
+
+
+
+PJ_END_DECL
+
+#endif /* __PJLIB_UTIL_SCANNER_CIS_BIT_H__ */
diff --git a/pjlib-util/include/pjlib-util/sha1.h b/pjlib-util/include/pjlib-util/sha1.h
new file mode 100644
index 0000000..f43e3c2
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/sha1.h
@@ -0,0 +1,80 @@
+/* $Id: sha1.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_SHA1_H__
+#define __PJLIB_UTIL_SHA1_H__
+
+/**
+ * @file sha1.h
+ * @brief SHA1 encryption implementation
+ */
+
+#include <pj/types.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJLIB_UTIL_SHA1 SHA1
+ * @ingroup PJLIB_UTIL_ENCRYPTION
+ * @{
+ */
+
+/** SHA1 context */
+typedef struct pj_sha1_context
+{
+ pj_uint32_t state[5]; /**< State */
+ pj_uint32_t count[2]; /**< Count */
+ pj_uint8_t buffer[64]; /**< Buffer */
+} pj_sha1_context;
+
+/** SHA1 digest size is 20 bytes */
+#define PJ_SHA1_DIGEST_SIZE 20
+
+
+/** Initialize the algorithm.
+ * @param ctx SHA1 context.
+ */
+PJ_DECL(void) pj_sha1_init(pj_sha1_context *ctx);
+
+/** Append a stream to the message.
+ * @param ctx SHA1 context.
+ * @param data Data.
+ * @param nbytes Length of data.
+ */
+PJ_DECL(void) pj_sha1_update(pj_sha1_context *ctx,
+ const pj_uint8_t *data,
+ const pj_size_t nbytes);
+
+/** Finish the message and return the digest.
+ * @param ctx SHA1 context.
+ * @param digest 16 byte digest.
+ */
+PJ_DECL(void) pj_sha1_final(pj_sha1_context *ctx,
+ pj_uint8_t digest[PJ_SHA1_DIGEST_SIZE]);
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+
+#endif /* __PJLIB_UTIL_SHA1_H__ */
+
diff --git a/pjlib-util/include/pjlib-util/srv_resolver.h b/pjlib-util/include/pjlib-util/srv_resolver.h
new file mode 100644
index 0000000..a3c4768
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/srv_resolver.h
@@ -0,0 +1,215 @@
+/* $Id: srv_resolver.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_SRV_RESOLVER_H__
+#define __PJLIB_UTIL_SRV_RESOLVER_H__
+
+/**
+ * @file srv_resolver.h
+ * @brief DNS SRV resolver
+ */
+#include <pjlib-util/resolver.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJ_DNS_SRV_RESOLVER DNS SRV Resolution Helper
+ * @ingroup PJ_DNS
+ * @{
+ *
+ * \section PJ_DNS_SRV_RESOLVER_INTRO DNS SRV Resolution Helper
+ *
+ * This module provides an even higher layer of abstraction for the DNS
+ * resolution framework, to resolve DNS SRV names.
+ *
+ * The #pj_dns_srv_resolve() function will asynchronously resolve the server
+ * name into IP address(es) with a single function call. If the SRV name
+ * contains multiple names, then each will be resolved with individual
+ * DNS A resolution to get the IP addresses. Upon successful completion,
+ * application callback will be called with each IP address of the
+ * target selected based on the load-balancing and fail-over criteria
+ * below.
+ *
+ * When the resolver fails to resolve the name using DNS SRV resolution
+ * (for example when the DNS SRV record is not present in the DNS server),
+ * the resolver will fallback to using DNS A record resolution to resolve
+ * the name.
+ *
+ * \subsection PJ_DNS_SRV_RESOLVER_FAILOVER_LOADBALANCE Load-Balancing and Fail-Over
+ *
+ * When multiple targets are returned in the DNS SRV response, server entries
+ * are selected based on the following rule (which is described in RFC 2782):
+ * - targets will be sorted based on the priority first.
+ * - for targets with the same priority, #pj_dns_srv_resolve() will select
+ * only one target according to its weight. To select this one target,
+ * the function associates running-sum for all targets, and generates
+ * a random number between zero and the total running-sum (inclusive).
+ * The target selected is the first target with running-sum greater than
+ * or equal to this random number.
+ *
+ * The above procedure will select one target for each priority, allowing
+ * application to fail-over to the next target when the previous target fails.
+ * These targets are returned in the #pj_dns_srv_record structure
+ * argument of the callback.
+ *
+ * \section PJ_DNS_SRV_RESOLVER_REFERENCE Reference
+ *
+ * Reference:
+ * - <A HREF="http://www.ietf.org/rfc/rfc2782.txt">RFC 2782</A>:
+ * A DNS RR for specifying the location of services (DNS SRV)
+ */
+
+/**
+ * Flags to be specified when starting the DNS SRV query.
+ */
+typedef enum pj_dns_srv_option
+{
+ /**
+ * Specify if the resolver should fallback with DNS A
+ * resolution when the SRV resolution fails. This option may
+ * be specified together with PJ_DNS_SRV_FALLBACK_AAAA to
+ * make the resolver fallback to AAAA if SRV resolution fails,
+ * and then to DNS A resolution if the AAAA resolution fails.
+ */
+ PJ_DNS_SRV_FALLBACK_A = 1,
+
+ /**
+ * Specify if the resolver should fallback with DNS AAAA
+ * resolution when the SRV resolution fails. This option may
+ * be specified together with PJ_DNS_SRV_FALLBACK_A to
+ * make the resolver fallback to AAAA if SRV resolution fails,
+ * and then to DNS A resolution if the AAAA resolution fails.
+ */
+ PJ_DNS_SRV_FALLBACK_AAAA = 2,
+
+ /**
+ * Specify if the resolver should try to resolve with DNS AAAA
+ * resolution first of each targets in the DNS SRV record. If
+ * this option is not specified, the SRV resolver will query
+ * the DNS A record for the target instead.
+ */
+ PJ_DNS_SRV_RESOLVE_AAAA = 4
+
+} pj_dns_srv_option;
+
+
+/**
+ * This structure represents DNS SRV records as the result of DNS SRV
+ * resolution using #pj_dns_srv_resolve().
+ */
+typedef struct pj_dns_srv_record
+{
+ /** Number of address records. */
+ unsigned count;
+
+ /** Address records. */
+ struct
+ {
+ /** Server priority (the lower the higher the priority). */
+ unsigned priority;
+
+ /** Server weight (the higher the more load it can handle). */
+ unsigned weight;
+
+ /** Port number. */
+ pj_uint16_t port;
+
+ /** The host address. */
+ pj_dns_a_record server;
+
+ } entry[PJ_DNS_SRV_MAX_ADDR];
+
+} pj_dns_srv_record;
+
+
+/** Opaque declaration for DNS SRV query */
+typedef struct pj_dns_srv_async_query pj_dns_srv_async_query;
+
+/**
+ * Type of callback function to receive notification from the resolver
+ * when the resolution process completes.
+ */
+typedef void pj_dns_srv_resolver_cb(void *user_data,
+ pj_status_t status,
+ const pj_dns_srv_record *rec);
+
+
+/**
+ * Start DNS SRV resolution for the specified name. The full name of the
+ * entry will be concatenated from \a res_name and \a domain_name fragments.
+ *
+ * @param domain_name The domain name part of the name.
+ * @param res_name The full service name, including the transport name
+ * and with all the leading underscore characters and
+ * ending dot (e.g. "_sip._udp.", "_stun._udp.").
+ * @param def_port The port number to be assigned to the resolved address
+ * when the DNS SRV resolution fails and the name is
+ * resolved with DNS A resolution.
+ * @param pool Memory pool used to allocate memory for the query.
+ * @param resolver The resolver instance.
+ * @param option Option flags, which can be constructed from
+ * #pj_dns_srv_option bitmask. Note that this argument
+ * was called "fallback_a" in pjsip version 0.8.0 and
+ * older, but the new option should be backward
+ * compatible with existing applications. If application
+ * specifies PJ_TRUE as "fallback_a" value, it will
+ * correspond to PJ_DNS_SRV_FALLBACK_A option.
+ * @param token Arbitrary data to be associated with this query when
+ * the calback is called.
+ * @param cb Pointer to callback function to receive the
+ * notification when the resolution process completes.
+ * @param p_query Optional pointer to receive the query object, if one
+ * was started. If this pointer is specified, a NULL may
+ * be returned if response cache is available immediately.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pj_dns_srv_resolve(const pj_str_t *domain_name,
+ const pj_str_t *res_name,
+ unsigned def_port,
+ pj_pool_t *pool,
+ pj_dns_resolver *resolver,
+ unsigned option,
+ void *token,
+ pj_dns_srv_resolver_cb *cb,
+ pj_dns_srv_async_query **p_query);
+
+
+/**
+ * Cancel an outstanding DNS SRV query.
+ *
+ * @param query The pending asynchronous query to be cancelled.
+ * @param notify If non-zero, the callback will be called with failure
+ * status to notify that the query has been cancelled.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error code,
+ */
+PJ_DECL(pj_status_t) pj_dns_srv_cancel_query(pj_dns_srv_async_query *query,
+ pj_bool_t notify);
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+
+#endif /* __PJLIB_UTIL_SRV_RESOLVER_H__ */
+
diff --git a/pjlib-util/include/pjlib-util/string.h b/pjlib-util/include/pjlib-util/string.h
new file mode 100644
index 0000000..8487a38
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/string.h
@@ -0,0 +1,102 @@
+/* $Id: string.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_STRING_H__
+#define __PJLIB_UTIL_STRING_H__
+
+/**
+ * @file string.h
+ * @brief More string functions.
+ */
+
+#include <pj/types.h>
+#include <pjlib-util/scanner.h>
+
+/**
+ * @defgroup PJLIB_UTIL_STRING String Escaping Utilities
+ * @ingroup PJLIB_TEXT
+ * @{
+ */
+
+PJ_BEGIN_DECL
+
+/**
+ * Unescape string. If source string does not contain any escaped
+ * characters, the function would simply return the original string.
+ * Otherwise a new string will be allocated.
+ *
+ * @param pool Pool to allocate the string.
+ * @param src Source string to unescape.
+ *
+ * @return String with no escaped characters.
+ */
+PJ_DECL(pj_str_t) pj_str_unescape( pj_pool_t *pool, const pj_str_t *src);
+
+/**
+ * Unescape string to destination.
+ *
+ * @param dst Target string.
+ * @param src Source string.
+ *
+ * @return Target string.
+ */
+PJ_DECL(pj_str_t*) pj_strcpy_unescape(pj_str_t *dst, const pj_str_t *src);
+
+/**
+ * Copy string to destination while escaping reserved characters, up to
+ * the specified maximum length.
+ *
+ * @param dst Target string.
+ * @param src Source string.
+ * @param max Maximum length to copy to target string.
+ * @param unres Unreserved characters, which are allowed to appear
+ * unescaped.
+ *
+ * @return The target string if all characters have been copied
+ * successfully, or NULL if there's not enough buffer to
+ * escape the strings.
+ */
+PJ_DECL(pj_str_t*) pj_strncpy_escape(pj_str_t *dst, const pj_str_t *src,
+ pj_ssize_t max, const pj_cis_t *unres);
+
+
+/**
+ * Copy string to destination while escaping reserved characters, up to
+ * the specified maximum length.
+ *
+ * @param dst Target string.
+ * @param src Source string.
+ * @param max Maximum length to copy to target string.
+ * @param unres Unreserved characters, which are allowed to appear
+ * unescaped.
+ *
+ * @return The length of the destination, or -1 if there's not
+ * enough buffer.
+ */
+PJ_DECL(pj_ssize_t) pj_strncpy2_escape(char *dst, const pj_str_t *src,
+ pj_ssize_t max, const pj_cis_t *unres);
+
+PJ_END_DECL
+
+
+/**
+ * @}
+ */
+
+#endif /* __PJLIB_UTIL_STRING_H__ */
diff --git a/pjlib-util/include/pjlib-util/stun_simple.h b/pjlib-util/include/pjlib-util/stun_simple.h
new file mode 100644
index 0000000..3d10379
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/stun_simple.h
@@ -0,0 +1,209 @@
+/* $Id: stun_simple.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJSTUN_H__
+#define __PJSTUN_H__
+
+/**
+ * @file stun.h
+ * @brief STUN client.
+ */
+
+#include <pjlib-util/types.h>
+#include <pj/sock.h>
+
+
+PJ_BEGIN_DECL
+
+/*
+ * This enumeration describes STUN message types.
+ */
+typedef enum pjstun_msg_type
+{
+ PJSTUN_BINDING_REQUEST = 0x0001,
+ PJSTUN_BINDING_RESPONSE = 0x0101,
+ PJSTUN_BINDING_ERROR_RESPONSE = 0x0111,
+ PJSTUN_SHARED_SECRET_REQUEST = 0x0002,
+ PJSTUN_SHARED_SECRET_RESPONSE = 0x0102,
+ PJSTUN_SHARED_SECRET_ERROR_RESPONSE = 0x0112
+} pjstun_msg_type;
+
+
+/*
+ * This enumeration describes STUN attribute types.
+ */
+typedef enum pjstun_attr_type
+{
+ PJSTUN_ATTR_MAPPED_ADDR = 1,
+ PJSTUN_ATTR_RESPONSE_ADDR,
+ PJSTUN_ATTR_CHANGE_REQUEST,
+ PJSTUN_ATTR_SOURCE_ADDR,
+ PJSTUN_ATTR_CHANGED_ADDR,
+ PJSTUN_ATTR_USERNAME,
+ PJSTUN_ATTR_PASSWORD,
+ PJSTUN_ATTR_MESSAGE_INTEGRITY,
+ PJSTUN_ATTR_ERROR_CODE,
+ PJSTUN_ATTR_UNKNOWN_ATTRIBUTES,
+ PJSTUN_ATTR_REFLECTED_FROM,
+ PJSTUN_ATTR_XOR_MAPPED_ADDR = 0x0020
+} pjstun_attr_type;
+
+
+/*
+ * This structre describes STUN message header.
+ */
+typedef struct pjstun_msg_hdr
+{
+ pj_uint16_t type;
+ pj_uint16_t length;
+ pj_uint32_t tsx[4];
+} pjstun_msg_hdr;
+
+
+/*
+ * This structre describes STUN attribute header.
+ */
+typedef struct pjstun_attr_hdr
+{
+ pj_uint16_t type;
+ pj_uint16_t length;
+} pjstun_attr_hdr;
+
+
+/*
+ * This structre describes STUN MAPPED-ADDR attribute.
+ */
+typedef struct pjstun_mapped_addr_attr
+{
+ pjstun_attr_hdr hdr;
+ pj_uint8_t ignored;
+ pj_uint8_t family;
+ pj_uint16_t port;
+ pj_uint32_t addr;
+} pjstun_mapped_addr_attr;
+
+typedef pjstun_mapped_addr_attr pjstun_response_addr_attr;
+typedef pjstun_mapped_addr_attr pjstun_changed_addr_attr;
+typedef pjstun_mapped_addr_attr pjstun_src_addr_attr;
+typedef pjstun_mapped_addr_attr pjstun_reflected_form_attr;
+
+typedef struct pjstun_change_request_attr
+{
+ pjstun_attr_hdr hdr;
+ pj_uint32_t value;
+} pjstun_change_request_attr;
+
+typedef struct pjstun_username_attr
+{
+ pjstun_attr_hdr hdr;
+ pj_uint32_t value[1];
+} pjstun_username_attr;
+
+typedef pjstun_username_attr pjstun_password_attr;
+
+typedef struct pjstun_error_code_attr
+{
+ pjstun_attr_hdr hdr;
+ pj_uint16_t ignored;
+ pj_uint8_t err_class;
+ pj_uint8_t number;
+ char reason[4];
+} pjstun_error_code_attr;
+
+typedef struct pjstun_msg
+{
+ pjstun_msg_hdr *hdr;
+ int attr_count;
+ pjstun_attr_hdr *attr[PJSTUN_MAX_ATTR];
+} pjstun_msg;
+
+/* STUN message API (stun.c). */
+
+PJ_DECL(pj_status_t) pjstun_create_bind_req( pj_pool_t *pool,
+ void **msg, pj_size_t *len,
+ pj_uint32_t id_hi,
+ pj_uint32_t id_lo);
+PJ_DECL(pj_status_t) pjstun_parse_msg( void *buf, pj_size_t len,
+ pjstun_msg *msg);
+PJ_DECL(void*) pjstun_msg_find_attr( pjstun_msg *msg, pjstun_attr_type t);
+
+
+/**
+ * @defgroup PJLIB_UTIL_STUN_CLIENT Simple STUN Helper
+ * @ingroup PJ_PROTOCOLS
+ * @brief A simple and small footprint STUN resolution helper
+ * @{
+ *
+ * This is the older implementation of STUN client, with only one function
+ * provided (pjstun_get_mapped_addr()) to retrieve the public IP address
+ * of multiple sockets.
+ */
+
+/**
+ * This is the main function to request the mapped address of local sockets
+ * to multiple STUN servers. This function is able to find the mapped
+ * addresses of multiple sockets simultaneously, and for each socket, two
+ * requests will be sent to two different STUN servers to see if both servers
+ * get the same public address for the same socket. (Note that application can
+ * specify the same address for the two servers, but still two requests will
+ * be sent for each server).
+ *
+ * This function will perform necessary retransmissions of the requests if
+ * response is not received within a predetermined period. When all responses
+ * have been received, the function will compare the mapped addresses returned
+ * by the servers, and when both are equal, the address will be returned in
+ * \a mapped_addr argument.
+ *
+ * @param pf The pool factory where memory will be allocated from.
+ * @param sock_cnt Number of sockets in the socket array.
+ * @param sock Array of local UDP sockets which public addresses are
+ * to be queried from the STUN servers.
+ * @param srv1 Host name or IP address string of the first STUN
+ * server.
+ * @param port1 The port number of the first STUN server.
+ * @param srv2 Host name or IP address string of the second STUN
+ * server.
+ * @param port2 The port number of the second STUN server.
+ * @param mapped_addr Array to receive the mapped public address of the local
+ * UDP sockets, when the function returns PJ_SUCCESS.
+ *
+ * @return This functions returns PJ_SUCCESS if responses are
+ * received from all servers AND all servers returned the
+ * same mapped public address. Otherwise this function may
+ * return one of the following error codes:
+ * - PJLIB_UTIL_ESTUNNOTRESPOND: no respons from servers.
+ * - PJLIB_UTIL_ESTUNSYMMETRIC: different mapped addresses
+ * are returned by servers.
+ * - etc.
+ *
+ */
+PJ_DECL(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf,
+ int sock_cnt, pj_sock_t sock[],
+ const pj_str_t *srv1, int port1,
+ const pj_str_t *srv2, int port2,
+ pj_sockaddr_in mapped_addr[]);
+
+PJ_END_DECL
+
+/**
+ * @}
+ */
+
+#endif /* __PJSTUN_H__ */
+
diff --git a/pjlib-util/include/pjlib-util/types.h b/pjlib-util/include/pjlib-util/types.h
new file mode 100644
index 0000000..899c27b
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/types.h
@@ -0,0 +1,95 @@
+/* $Id: types.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_TYPES_H__
+#define __PJLIB_UTIL_TYPES_H__
+
+/**
+ * @file types.h
+ * @brief PJLIB-UTIL types.
+ */
+
+#include <pj/types.h>
+#include <pjlib-util/config.h>
+
+/**
+ * @defgroup PJLIB_UTIL_BASE Base
+ * @{
+ */
+
+PJ_BEGIN_DECL
+
+/**
+ * Initialize PJLIB UTIL (defined in errno.c)
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjlib_util_init(void);
+
+
+
+PJ_END_DECL
+
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup PJLIB_TEXT Text and String Manipulation
+ */
+
+/**
+ * @defgroup PJ_PROTOCOLS Protocols
+ */
+
+/**
+ * @defgroup PJ_FILE_FMT File Formats
+ */
+
+/**
+ * @mainpage PJLIB-UTIL
+ *
+ * \n
+ * \n
+ * \n
+ * This is the documentation of PJLIB-UTIL, an auxiliary library providing
+ * adjunct functions to PJLIB.
+ *
+ * Please go to the <A HREF="modules.htm"><B>Table of Contents</B></A> page
+ * for list of modules.
+ *
+ *
+ * \n
+ * \n
+ * \n
+ * \n
+ * \n
+ * \n
+ * \n
+ * \n
+ * \n
+ * \n
+ * \n
+ * \n
+ * \n
+ */
+
+#endif /* __PJLIB_UTIL_TYPES_H__ */
+
diff --git a/pjlib-util/include/pjlib-util/xml.h b/pjlib-util/include/pjlib-util/xml.h
new file mode 100644
index 0000000..81dc6c7
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/xml.h
@@ -0,0 +1,246 @@
+/* $Id: xml.h 3553 2011-05-05 06:14:19Z nanang $ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJ_XML_H__
+#define __PJ_XML_H__
+
+/**
+ * @file xml.h
+ * @brief PJLIB XML Parser/Helper.
+ */
+
+#include <pj/types.h>
+#include <pj/list.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJ_TINY_XML Mini/Tiny XML Parser/Helper
+ * @ingroup PJ_FILE_FMT
+ * @{
+ */
+
+/** Typedef for XML attribute. */
+typedef struct pj_xml_attr pj_xml_attr;
+
+/** Typedef for XML nodes. */
+typedef struct pj_xml_node pj_xml_node;
+
+/** This structure declares XML attribute. */
+struct pj_xml_attr
+{
+ PJ_DECL_LIST_MEMBER(pj_xml_attr); /**< Standard list elements. */
+ pj_str_t name; /**< Attribute name. */
+ pj_str_t value; /**< Attribute value. */
+};
+
+/** This structure describes XML node head inside XML node structure.
+ */
+typedef struct pj_xml_node_head
+{
+ PJ_DECL_LIST_MEMBER(pj_xml_node); /**< Standard list elements. */
+} pj_xml_node_head;
+
+/** This structure describes XML node. */
+struct pj_xml_node
+{
+ PJ_DECL_LIST_MEMBER(pj_xml_node); /**< List @a prev and @a next member */
+ pj_str_t name; /**< Node name. */
+ pj_xml_attr attr_head; /**< Attribute list. */
+ pj_xml_node_head node_head; /**< Node list. */
+ pj_str_t content; /**< Node content. */
+};
+
+/**
+ * Parse XML message into XML document with a single root node. The parser
+ * is capable of parsing XML processing instruction construct ("<?") and
+ * XML comments ("<!--"), however such constructs will be ignored and will not
+ * be included in the resulted XML node tree.
+ *
+ * @param pool Pool to allocate memory from.
+ * @param msg The XML message to parse.
+ * @param len The length of the message.
+ *
+ * @return XML root node, or NULL if the XML document can not be parsed.
+ */
+PJ_DECL(pj_xml_node*) pj_xml_parse( pj_pool_t *pool, char *msg, pj_size_t len);
+
+
+/**
+ * Print XML into XML message. Note that the function WILL NOT NULL terminate
+ * the output.
+ *
+ * @param node The XML node to print.
+ * @param buf Buffer to hold the output message.
+ * @param len The length of the buffer.
+ * @param prolog If set to nonzero, will print XML prolog ("<?xml..")
+ *
+ * @return The size of the printed message, or -1 if there is not
+ * sufficient space in the buffer to print the message.
+ */
+PJ_DECL(int) pj_xml_print( const pj_xml_node *node, char *buf, pj_size_t len,
+ pj_bool_t prolog);
+
+/**
+ * Clone XML node and all subnodes.
+ *
+ * @param pool Pool to allocate memory for new nodes.
+ * @param rhs The node to clone.
+ *
+ * @return Cloned XML node, or NULL on fail.
+ */
+PJ_DECL(pj_xml_node*) pj_xml_clone( pj_pool_t *pool, const pj_xml_node *rhs);
+
+
+/**
+ * Create an empty node.
+ *
+ * @param pool Pool.
+ * @param name Node name.
+ *
+ * @return The new node.
+ */
+PJ_DECL(pj_xml_node*) pj_xml_node_new(pj_pool_t *pool, const pj_str_t *name);
+
+
+/**
+ * Create new XML attribute.
+ *
+ * @param pool Pool.
+ * @param name Attribute name.
+ * @param value Attribute value.
+ *
+ * @return The new XML attribute.
+ */
+PJ_DECL(pj_xml_attr*) pj_xml_attr_new(pj_pool_t *pool, const pj_str_t *name,
+ const pj_str_t *value);
+
+/**
+ * Add node to another node.
+ *
+ * @param parent Parent node.
+ * @param node Node to be added to parent.
+ */
+PJ_DECL(void) pj_xml_add_node( pj_xml_node *parent, pj_xml_node *node );
+
+
+/**
+ * Add attribute to a node.
+ *
+ * @param node Node.
+ * @param attr Attribute to add to node.
+ */
+PJ_DECL(void) pj_xml_add_attr( pj_xml_node *node, pj_xml_attr *attr );
+
+/**
+ * Find first direct child node with the specified name.
+ *
+ * @param parent Parent node.
+ * @param name Node name to find.
+ *
+ * @return XML node found or NULL.
+ */
+PJ_DECL(pj_xml_node*) pj_xml_find_node(const pj_xml_node *parent,
+ const pj_str_t *name);
+
+/**
+ * Find next direct child node with the specified name.
+ *
+ * @param parent Parent node.
+ * @param node node->next is the starting point.
+ * @param name Node name to find.
+ *
+ * @return XML node found or NULL.
+ */
+PJ_DECL(pj_xml_node*) pj_xml_find_next_node(const pj_xml_node *parent,
+ const pj_xml_node *node,
+ const pj_str_t *name);
+
+/**
+ * Recursively find the first node with the specified name in the child nodes
+ * and their children.
+ *
+ * @param parent Parent node.
+ * @param name Node name to find.
+ *
+ * @return XML node found or NULL.
+ */
+PJ_DECL(pj_xml_node*) pj_xml_find_node_rec(const pj_xml_node *parent,
+ const pj_str_t *name);
+
+
+/**
+ * Find first attribute within a node with the specified name and optional
+ * value.
+ *
+ * @param node XML Node.
+ * @param name Attribute name to find.
+ * @param value Optional value to match.
+ *
+ * @return XML attribute found, or NULL.
+ */
+PJ_DECL(pj_xml_attr*) pj_xml_find_attr(const pj_xml_node *node,
+ const pj_str_t *name,
+ const pj_str_t *value);
+
+
+/**
+ * Find a direct child node with the specified name and match the function.
+ *
+ * @param parent Parent node.
+ * @param name Optional name. If this is NULL, the name will not be
+ * matched.
+ * @param data Data to be passed to matching function.
+ * @param match Optional matching function.
+ *
+ * @return The first matched node, or NULL.
+ */
+PJ_DECL(pj_xml_node*) pj_xml_find( const pj_xml_node *parent,
+ const pj_str_t *name,
+ const void *data,
+ pj_bool_t (*match)(const pj_xml_node *,
+ const void*));
+
+
+/**
+ * Recursively find a child node with the specified name and match the
+ * function.
+ *
+ * @param parent Parent node.
+ * @param name Optional name. If this is NULL, the name will not be
+ * matched.
+ * @param data Data to be passed to matching function.
+ * @param match Optional matching function.
+ *
+ * @return The first matched node, or NULL.
+ */
+PJ_DECL(pj_xml_node*) pj_xml_find_rec(const pj_xml_node *parent,
+ const pj_str_t *name,
+ const void *data,
+ pj_bool_t (*match)(const pj_xml_node*,
+ const void*));
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+#endif /* __PJ_XML_H__ */