diff options
author | David M. Lee <dlee@digium.com> | 2013-01-07 14:24:28 -0600 |
---|---|---|
committer | David M. Lee <dlee@digium.com> | 2013-01-07 14:24:28 -0600 |
commit | f3ab456a17af1c89a6e3be4d20c5944853df1cb0 (patch) | |
tree | d00e1a332cd038a6d906a1ea0ac91e1a4458e617 /pjlib-util/include |
Import pjproject-2.0.1
Diffstat (limited to 'pjlib-util/include')
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__ */ |