initial commit

This commit is contained in:
Dan Bastone committed 2021-10-29 14:41:03 -04:00
commit 636959b37b
2474 files changed
+1343178

No files matched your search

@@ -0,0 +1,76 @@
/* $Id$ */
/*
* 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 and utilities */
#include <pjlib-util/scanner.h>
#include <pjlib-util/string.h>
/* XML */
#include <pjlib-util/xml.h>
/* JSON */
#include <pjlib-util/json.h>
/* Old STUN */
#include <pjlib-util/stun_simple.h>
/* PCAP */
#include <pjlib-util/pcap.h>
/* HTTP */
#include <pjlib-util/http_client.h>
/** CLI **/
#include <pjlib-util/cli.h>
#include <pjlib-util/cli_console.h>
#include <pjlib-util/cli_telnet.h>
#endif /* __PJLIB_UTIL_H__ */
@@ -0,0 +1,92 @@
/* $Id$ */
/*
* 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__ */
@@ -0,0 +1,531 @@
/* $Id$ */
/*
* Copyright (C) 2010 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_CLI_H__
#define __PJLIB_UTIL_CLI_H__
/**
* @file cli.h
* @brief Command Line Interface
*/
#include <pjlib-util/types.h>
#include <pj/list.h>
PJ_BEGIN_DECL
/**
* @defgroup PJLIB_UTIL_CLI Command Line Interface Framework
* @{
* A CLI framework features an interface for defining command specification,
* parsing, and executing a command.
* It also features an interface to communicate with various front-ends,
* such as console, telnet.
* Application normally needs only one CLI instance to be created.
* On special cases, application could also create multiple CLI
* instances, with each instance has specific command structure.
*
\verbatim
| vid help Show this help screen |
| vid enable|disable Enable or disable video in next offer/answer |
| vid call add Add video stream for current call |
| vid call cap N ID Set capture dev ID for stream #N in current call |
| disable_codec g711|g722 Show this help screen |
<CMD name='vid' id='0' desc="">
<CMD name='help' id='0' desc='' />
<CMD name='enable' id='0' desc='' />
<CMD name='disable' id='0' desc='' />
<CMD name='call' id='0' desc='' >
<CMD name='add' id='101' desc='...' />
<CMD name='cap' id='102' desc='...' >
<ARG name='streamno' type='int' desc='...' id='1'/>
<ARG name='devid' type='int' optional='1' id='2'/>
</CMD>
</CMD>
</CMD>
<CMD name='disable_codec' id=0 desc="">
<ARG name='codec_list' type='choice' id='3'>
<CHOICE value='g711'/>
<CHOICE value='g722'/>
</ARG>
</CMD>
\endverbatim
*/
/**
* This opaque structure represents a CLI application. A CLI application is
* the root placeholder of other CLI objects. In an application, one (and
* normally only one) CLI application instance needs to be created.
*/
typedef struct pj_cli_t pj_cli_t;
/**
* Type of command id.
*/
typedef int pj_cli_cmd_id;
/**
* This describes the parameters to be specified when creating a CLI
* application with pj_cli_create(). Application MUST initialize this
* structure by calling pj_cli_cfg_default() before using it.
*/
typedef struct pj_cli_cfg
{
/**
* The application name, which will be used in places such as logs.
* This field is mandatory.
*/
pj_str_t name;
/**
* Optional application title, which will be used in places such as
* window title. If not specified, the application name will be used
* as the title.
*/
pj_str_t title;
/**
* The pool factory where all memory allocations will be taken from.
* This field is mandatory.
*/
pj_pool_factory *pf;
} pj_cli_cfg;
/**
* Type of argument id.
*/
typedef int pj_cli_arg_id;
/**
* Forward declaration of pj_cli_cmd_spec structure.
*/
typedef struct pj_cli_cmd_spec pj_cli_cmd_spec;
/**
* Forward declaration for pj_cli_sess, which will be declared in cli_imp.h.
*/
typedef struct pj_cli_sess pj_cli_sess;
/**
* Forward declaration for CLI front-end.
*/
typedef struct pj_cli_front_end pj_cli_front_end;
/**
* Forward declaration for CLI argument spec structure.
*/
typedef struct pj_cli_arg_spec pj_cli_arg_spec;
/**
* This structure contains the command to be executed by command handler.
*/
typedef struct pj_cli_cmd_val
{
/** The session on which the command was executed on. */
pj_cli_sess *sess;
/** The command specification being executed. */
const pj_cli_cmd_spec *cmd;
/** Number of argvs. */
int argc;
/** Array of args, with argv[0] specifies the name of the cmd. */
pj_str_t argv[PJ_CLI_MAX_ARGS];
} pj_cli_cmd_val;
/**
* This structure contains the hints information for the end user.
* This structure could contain either command or argument information.
* The front-end will format the information and present it to the user.
*/
typedef struct pj_cli_hint_info
{
/**
* The hint value.
*/
pj_str_t name;
/**
* The hint type.
*/
pj_str_t type;
/**
* Helpful description of the hint value.
*/
pj_str_t desc;
} pj_cli_hint_info;
/**
* This structure contains extra information returned by pj_cli_sess_exec()/
* pj_cli_sess_parse().
* Upon return from the function, various other fields in this structure will
* be set by the function.
*/
typedef struct pj_cli_exec_info
{
/**
* If command parsing failed, on return this will point to the location
* where the failure occurs, otherwise the value will be set to -1.
*/
int err_pos;
/**
* If a command matching the command in the cmdline was found, on return
* this will be set to the command id of the command, otherwise it will be
* set to PJ_CLI_INVALID_CMD_ID.
*/
pj_cli_cmd_id cmd_id;
/**
* If a command was executed, on return this will be set to the return
* value of the command, otherwise it will contain PJ_SUCCESS.
*/
pj_status_t cmd_ret;
/**
* The number of hint elements
**/
unsigned hint_cnt;
/**
* If pj_cli_sess_parse() fails because of a missing argument or ambigous
* command/argument, the function returned PJ_CLI_EMISSINGARG or
* PJ_CLI_EAMBIGUOUS error.
* This field will contain the hint information. This is useful to give
* helpful information to the end_user.
*/
pj_cli_hint_info hint[PJ_CLI_MAX_HINTS];
} pj_cli_exec_info;
/**
* This structure contains the information returned from the dynamic
* argument callback.
*/
typedef struct pj_cli_arg_choice_val
{
/**
* The argument choice value
*/
pj_str_t value;
/**
* Helpful description of the choice value. This text will be used when
* displaying the help texts for the choice value
*/
pj_str_t desc;
} pj_cli_arg_choice_val;
/**
* This structure contains the parameters for pj_cli_get_dyn_choice
*/
typedef struct pj_cli_dyn_choice_param
{
/**
* The session on which the command was executed on.
*/
pj_cli_sess *sess;
/**
* The command being processed.
*/
pj_cli_cmd_spec *cmd;
/**
* The argument id.
*/
pj_cli_arg_id arg_id;
/**
* The maximum number of values that the choice can hold.
*/
unsigned max_cnt;
/**
* The pool to allocate memory from.
*/
pj_pool_t *pool;
/**
* The choice values count.
*/
unsigned cnt;
/**
* Array containing the valid choice values.
*/
pj_cli_arg_choice_val choice[PJ_CLI_MAX_CHOICE_VAL];
} pj_cli_dyn_choice_param;
/**
* This specifies the callback type for argument handlers, which will be
* called to get the valid values of the choice type arguments.
*/
typedef void (*pj_cli_get_dyn_choice) (pj_cli_dyn_choice_param *param);
/**
* This specifies the callback type for command handlers, which will be
* executed when the specified command is invoked.
*
* @param cmd_val The command that is specified by the user.
*
* @return Return the status of the command execution.
*/
typedef pj_status_t (*pj_cli_cmd_handler)(pj_cli_cmd_val *cval);
/**
* Write a log message to the CLI application. The CLI application
* will send the log message to all the registered front-ends.
*
* @param cli The CLI application instance.
* @param level Verbosity level of this message message.
* @param buffer The message itself.
* @param len Length of this message.
*/
PJ_DECL(void) pj_cli_write_log(pj_cli_t *cli,
int level,
const char *buffer,
int len);
/**
* Create a new CLI application instance.
*
* @param cfg CLI application creation parameters.
* @param p_cli Pointer to receive the returned instance.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_cli_create(pj_cli_cfg *cfg,
pj_cli_t **p_cli);
/**
* This specifies the function to get the id of the specified command
*
* @param cmd The specified command.
*
* @return The command id
*/
PJ_DECL(pj_cli_cmd_id) pj_cli_get_cmd_id(const pj_cli_cmd_spec *cmd);
/**
* Get the internal parameter of the CLI instance.
*
* @param cli The CLI application instance.
*
* @return CLI parameter instance.
*/
PJ_DECL(pj_cli_cfg*) pj_cli_get_param(pj_cli_t *cli);
/**
* Call this to signal application shutdown. Typically application would
* call this from it's "Quit" menu or similar command to quit the
* application.
*
* See also pj_cli_sess_end_session() to end a session instead of quitting the
* whole application.
*
* @param cli The CLI application instance.
* @param req The session on which the shutdown request is
* received.
* @param restart Indicate whether application restart is wanted.
*/
PJ_DECL(void) pj_cli_quit(pj_cli_t *cli, pj_cli_sess *req,
pj_bool_t restart);
/**
* Check if application shutdown or restart has been requested.
*
* @param cli The CLI application instance.
*
* @return PJ_TRUE if pj_cli_quit() has been called.
*/
PJ_DECL(pj_bool_t) pj_cli_is_quitting(pj_cli_t *cli);
/**
* Check if application restart has been requested.
*
* @param cli The CLI application instance.
*
* @return PJ_TRUE if pj_cli_quit() has been called with
* restart parameter set.
*/
PJ_DECL(pj_bool_t) pj_cli_is_restarting(pj_cli_t *cli);
/**
* Destroy a CLI application instance. This would also close all sessions
* currently running for this CLI application.
*
* @param cli The CLI application.
*/
PJ_DECL(void) pj_cli_destroy(pj_cli_t *cli);
/**
* Initialize a pj_cli_cfg with its default values.
*
* @param param The instance to be initialized.
*/
PJ_DECL(void) pj_cli_cfg_default(pj_cli_cfg *param);
/**
* Register a front end to the CLI application.
*
* @param CLI The CLI application.
* @param fe The CLI front end to be registered.
*/
PJ_DECL(void) pj_cli_register_front_end(pj_cli_t *cli,
pj_cli_front_end *fe);
/**
* Create a new complete command specification from an XML node text and
* register it to the CLI application.
*
* Note that the input string MUST be NULL terminated.
*
* @param cli The CLI application.
* @param group Optional group to which this command will be added
* to, or specify NULL if this command is a root
* command.
* @param xml Input string containing XML node text for the
* command, MUST be NULL terminated.
* @param handler Function handler for the command. This must be NULL
* if the command specifies a command group.
* @param p_cmd Optional pointer to store the newly created
* specification.
* @param get_choice Function handler for the argument. Specify this for
* dynamic choice type arguments.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_cli_add_cmd_from_xml(pj_cli_t *cli,
pj_cli_cmd_spec *group,
const pj_str_t *xml,
pj_cli_cmd_handler handler,
pj_cli_cmd_spec **p_cmd,
pj_cli_get_dyn_choice get_choice);
/**
* Initialize pj_cli_exec_info with its default values.
*
* @param param The param to be initialized.
*/
PJ_DECL(void) pj_cli_exec_info_default(pj_cli_exec_info *param);
/**
* Write a log message to the specific CLI session.
*
* @param sess The CLI active session.
* @param buffer The message itself.
* @param len Length of this message.
*/
PJ_DECL(void) pj_cli_sess_write_msg(pj_cli_sess *sess,
const char *buffer,
pj_size_t len);
/**
* Parse an input cmdline string. The first word of the command line is the
* command itself, which will be matched against command specifications
* registered in the CLI application.
*
* Zero or more arguments follow the command name. Arguments are separated by
* one or more whitespaces. Argument may be placed inside a pair of quotes,
* double quotes, '{' and '}', or '[' and ']' pairs. This is useful when the
* argument itself contains whitespaces or other restricted characters. If
* the quote character itself is to appear in the argument, the argument then
* must be quoted with different quote characters. There is no character
* escaping facility provided by this function (such as the use of backslash
* '\' character).
*
* The cmdline may be followed by an extra newline (LF or CR-LF characters),
* which will be removed by the function. However any more characters
* following this newline will cause an error to be returned.
*
* @param sess The CLI session.
* @param cmdline The command line string to be parsed.
* @param val Structure to store the parsing result.
* @param pool The pool to allocate memory from.
* @param info Additional info to be returned regarding the parsing.
*
* @return This function returns the status of the parsing,
* which can be one of the following :
* - PJ_SUCCESS: a command was executed successfully.
* - PJ_EINVAL: invalid parameter to this function.
* - PJ_ENOTFOUND: command is not found.
* - PJ_CLI_EAMBIGUOUS: command/argument is ambiguous.
* - PJ_CLI_EMISSINGARG: missing argument.
* - PJ_CLI_EINVARG: invalid command argument.
* - PJ_CLI_EEXIT: "exit" has been called to end
* the current session. This is a signal for the
* application to end it's main loop.
*/
PJ_DECL(pj_status_t) pj_cli_sess_parse(pj_cli_sess *sess,
char *cmdline,
pj_cli_cmd_val *val,
pj_pool_t *pool,
pj_cli_exec_info *info);
/**
* End the specified session, and destroy it to release all resources used
* by the session.
*
* See also pj_cli_sess and pj_cli_front_end for more info regarding the
* creation process.
* See also pj_cli_quit() to quit the whole application instead.
*
* @param sess The CLI session to be destroyed.
*/
PJ_DECL(void) pj_cli_sess_end_session(pj_cli_sess *sess);
/**
* Execute a command line. This function will parse the input string to find
* the appropriate command and verify whether the string matches the command
* specifications. If matches, the command will be executed, and the return
* value of the command will be set in the \a cmd_ret field of the \a info
* argument, if specified.
*
* See also pj_cli_sess_parse() for more info regarding the cmdline format.
*
* @param sess The CLI session.
* @param cmdline The command line string to be executed.
* @param pool The pool to allocate memory from.
* @param info Optional pointer to receive additional information
* related to the execution of the command (such as
* the command return value).
*
* @return This function returns the status of the command
* parsing and execution (note that the return value
* of the handler itself will be returned in \a info
* argument, if specified). Please see the return value
* of pj_cli_sess_parse() for possible return values.
*/
PJ_DECL(pj_status_t) pj_cli_sess_exec(pj_cli_sess *sess,
char *cmdline,
pj_pool_t *pool,
pj_cli_exec_info *info);
/**
* @}
*/
PJ_END_DECL
#endif /* __PJLIB_UTIL_CLI_H__ */
@@ -0,0 +1,117 @@
/* $Id$ */
/*
* Copyright (C) 2010 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_CLI_CONSOLE_H__
#define __PJLIB_UTIL_CLI_CONSOLE_H__
/**
* @file cli_console.h
* @brief Command Line Interface Console Front End API
*/
#include <pjlib-util/cli_imp.h>
PJ_BEGIN_DECL
/**
* @ingroup PJLIB_UTIL_CLI_IMP
* @{
*
*/
/**
* This structure contains various options for CLI console front-end.
* Application must call pj_cli_console_cfg_default() to initialize
* this structure with its default values.
*/
typedef struct pj_cli_console_cfg
{
/**
* Default log verbosity level for the session.
*
* Default value: PJ_CLI_CONSOLE_LOG_LEVEL
*/
int log_level;
/**
* Specify text message as a prompt string to user.
*
* Default: empty
*/
pj_str_t prompt_str;
/**
* Specify the command to quit the application.
*
* Default: empty
*/
pj_str_t quit_command;
} pj_cli_console_cfg;
/**
* Initialize pj_cli_console_cfg with its default values.
*
* @param param The structure to be initialized.
*/
PJ_DECL(void) pj_cli_console_cfg_default(pj_cli_console_cfg *param);
/**
* Create a console front-end for the specified CLI application, and return
* the only session instance for the console front end. On Windows operating
* system, this may open a new console window.
*
* @param cli The CLI application instance.
* @param param Optional console CLI parameters. If this value is
* NULL, default parameters will be used.
* @param p_sess Pointer to receive the session instance for the
* console front end.
* @param p_fe Optional pointer to receive the front-end instance
* of the console front-end just created.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_cli_console_create(pj_cli_t *cli,
const pj_cli_console_cfg *param,
pj_cli_sess **p_sess,
pj_cli_front_end **p_fe);
/**
* Retrieve a cmdline from console stdin and process the input accordingly.
*
* @param sess The CLI session.
* @param buf Pointer to receive the buffer.
* @param maxlen Maximum length to read.
*
* @return PJ_SUCCESS if an input was read
*/
PJ_DECL(pj_status_t) pj_cli_console_process(pj_cli_sess *sess,
char *buf,
unsigned maxlen);
/**
* @}
*/
PJ_END_DECL
#endif /* __PJLIB_UTIL_CLI_CONSOLE_H__ */
@@ -0,0 +1,208 @@
/* $Id$ */
/*
* Copyright (C) 2010 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_CLI_IMP_H__
#define __PJLIB_UTIL_CLI_IMP_H__
/**
* @file cli_imp.h
* @brief Command Line Interface Implementor's API
*/
#include <pjlib-util/cli.h>
PJ_BEGIN_DECL
/**
* @defgroup PJLIB_UTIL_CLI_IMP Command Line Interface Implementor's API
* @ingroup PJLIB_UTIL_CLI
* @{
*
*/
/**
* Default log level for console sessions.
*/
#ifndef PJ_CLI_CONSOLE_LOG_LEVEL
# define PJ_CLI_CONSOLE_LOG_LEVEL PJ_LOG_MAX_LEVEL
#endif
/**
* Default log level for telnet sessions.
*/
#ifndef PJ_CLI_TELNET_LOG_LEVEL
# define PJ_CLI_TELNET_LOG_LEVEL 4
#endif
/**
* Default port number for telnet daemon.
*/
#ifndef PJ_CLI_TELNET_PORT
# define PJ_CLI_TELNET_PORT 0
#endif
/**
* This enumeration specifies front end types.
*/
typedef enum pj_cli_front_end_type
{
PJ_CLI_CONSOLE_FRONT_END, /**< Console front end. */
PJ_CLI_TELNET_FRONT_END, /**< Telnet front end. */
PJ_CLI_HTTP_FRONT_END, /**< HTTP front end. */
PJ_CLI_GUI_FRONT_END /**< GUI front end. */
} pj_cli_front_end_type;
/**
* Front end operations. Only the CLI should call these functions
* directly.
*/
typedef struct pj_cli_front_end_op
{
/**
* Callback to write a log message to the appropriate sessions belonging
* to this front end. The front end would only send the log message to
* the session if the session's log verbosity level is greater than the
* level of this log message.
*
* @param fe The front end.
* @param level Verbosity level of this message message.
* @param data The message itself.
* @param len Length of this message.
*/
void (*on_write_log)(pj_cli_front_end *fe, int level,
const char *data, pj_size_t len);
/**
* Callback to be called when the application is quitting, to signal the
* front-end to end its main loop or any currently blocking functions,
* if any.
*
* @param fe The front end.
* @param req The session which requested the application quit.
*/
void (*on_quit)(pj_cli_front_end *fe, pj_cli_sess *req);
/**
* Callback to be called to close and self destroy the front-end. This
* must also close any active sessions created by this front-ends.
*
* @param fe The front end.
*/
void (*on_destroy)(pj_cli_front_end *fe);
} pj_cli_front_end_op;
/**
* This structure describes common properties of CLI front-ends. A front-
* end is a mean to interact with end user, for example the CLI application
* may interact with console, telnet, web, or even a GUI.
*
* Each end user's interaction will create an instance of pj_cli_sess.
*
* Application instantiates the front end by calling the appropriate
* function to instantiate them.
*/
struct pj_cli_front_end
{
/**
* Linked list members
*/
PJ_DECL_LIST_MEMBER(struct pj_cli_front_end);
/**
* Front end type.
*/
pj_cli_front_end_type type;
/**
* The CLI application.
*/
pj_cli_t *cli;
/**
* Front end operations.
*/
pj_cli_front_end_op *op;
};
/**
* Session operations.
*/
typedef struct pj_cli_sess_op
{
/**
* Callback to be called to close and self destroy the session.
*
* @param sess The session to destroy.
*/
void (*destroy)(pj_cli_sess *sess);
} pj_cli_sess_op;
/**
* This structure describes common properties of a CLI session. A CLI session
* is the interaction of an end user to the CLI application via a specific
* renderer, where the renderer can be console, telnet, web, or a GUI app for
* mobile. A session is created by its renderer, and it's creation procedures
* vary among renderer (for example, a telnet session is created when the
* end user connects to the application, while a console session is always
* instantiated once the program is run).
*/
struct pj_cli_sess
{
/**
* Linked list members
*/
PJ_DECL_LIST_MEMBER(struct pj_cli_sess);
/**
* Pointer to the front-end instance which created this session.
*/
pj_cli_front_end *fe;
/**
* Session operations.
*/
pj_cli_sess_op *op;
/**
* Text containing session info, which is filled by the renderer when
* the session is created.
*/
pj_str_t info;
/**
* Log verbosity of this session.
*/
int log_level;
};
/**
* @}
*/
PJ_END_DECL
#endif /* __PJLIB_UTIL_CLI_IMP_H__ */
@@ -0,0 +1,167 @@
/* $Id$ */
/*
* Copyright (C) 2010 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_CLI_TELNET_H__
#define __PJLIB_UTIL_CLI_TELNET_H__
/**
* @file cli_telnet.h
* @brief Command Line Interface Telnet Front End API
*/
#include <pjlib-util/cli_imp.h>
PJ_BEGIN_DECL
/**
* @ingroup PJLIB_UTIL_CLI_IMP
* @{
*
*/
/**
* This structure contains the information about the telnet.
* Application will get updated information each time the telnet is started/
* restarted.
*/
typedef struct pj_cli_telnet_info
{
/**
* The telnet's ip address.
*/
pj_str_t ip_address;
/**
* The telnet's port number.
*/
pj_uint16_t port;
/* Internal buffer for IP address */
char buf_[32];
} pj_cli_telnet_info;
/**
* This specifies the callback called when telnet is started
*
* @param status The status of telnet startup process.
*
*/
typedef void (*pj_cli_telnet_on_started)(pj_status_t status);
/**
* This structure contains various options to instantiate the telnet daemon.
* Application must call pj_cli_telnet_cfg_default() to initialize
* this structure with its default values.
*/
typedef struct pj_cli_telnet_cfg
{
/**
* Listening port number. The value may be 0 to let the system choose
* the first available port.
*
* Default value: PJ_CLI_TELNET_PORT
*/
pj_uint16_t port;
/**
* Ioqueue instance to be used. If this field is NULL, an internal
* ioqueue and worker thread will be created.
*/
pj_ioqueue_t *ioqueue;
/**
* Default log verbosity level for the session.
*
* Default value: PJ_CLI_TELNET_LOG_LEVEL
*/
int log_level;
/**
* Specify a password to be asked to the end user to access the
* application. Currently this is not implemented yet.
*
* Default: empty (no password)
*/
pj_str_t passwd;
/**
* Specify text message to be displayed to newly connected users.
* Currently this is not implemented yet.
*
* Default: empty
*/
pj_str_t welcome_msg;
/**
* Specify text message as a prompt string to user.
*
* Default: empty
*/
pj_str_t prompt_str;
/**
* Specify the pj_cli_telnet_on_started callback.
*
* Default: empty
*/
pj_cli_telnet_on_started on_started;
} pj_cli_telnet_cfg;
/**
* Initialize pj_cli_telnet_cfg with its default values.
*
* @param param The structure to be initialized.
*/
PJ_DECL(void) pj_cli_telnet_cfg_default(pj_cli_telnet_cfg *param);
/**
* Create, initialize, and start a telnet daemon for the application.
*
* @param cli The CLI application instance.
* @param param Optional parameters for creating the telnet daemon.
* If this value is NULL, default parameters will be used.
* @param p_fe Optional pointer to receive the front-end instance
* of the telnet front-end just created.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_cli_telnet_create(pj_cli_t *cli,
pj_cli_telnet_cfg *param,
pj_cli_front_end **p_fe);
/**
* Retrieve cli telnet info.
*
* @param telnet_info The telnet runtime information.
*
* @return PJ_SUCCESS on success.
*/
PJ_DECL(pj_status_t) pj_cli_telnet_get_info(pj_cli_front_end *fe,
pj_cli_telnet_info *info);
/**
* @}
*/
PJ_END_DECL
#endif /* __PJLIB_UTIL_CLI_TELNET_H__ */
@@ -0,0 +1,374 @@
/* $Id$ */
/*
* 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
/* **************************************************************************
* CLI configuration
*/
/**
* Initial pool size for CLI.
* Default: 1024 bytes
*/
#ifndef PJ_CLI_POOL_SIZE
# define PJ_CLI_POOL_SIZE 1024
#endif
/**
* Pool increment size for CLI.
* Default: 512 bytes
*/
#ifndef PJ_CLI_POOL_INC
# define PJ_CLI_POOL_INC 512
#endif
/**
* Maximum length of command buffer.
* Default: 512
*/
#ifndef PJ_CLI_MAX_CMDBUF
# define PJ_CLI_MAX_CMDBUF 512
#endif
/**
* Maximum command arguments.
* Default: 8
*/
#ifndef PJ_CLI_MAX_ARGS
# define PJ_CLI_MAX_ARGS 8
#endif
/**
* Maximum number of hints.
* Default: 32
*/
#ifndef PJ_CLI_MAX_HINTS
# define PJ_CLI_MAX_HINTS 32
#endif
/**
* Maximum short name version (shortcuts) for a command.
* Default: 4
*/
#ifndef PJ_CLI_MAX_SHORTCUTS
# define PJ_CLI_MAX_SHORTCUTS 4
#endif
/**
* Initial pool size for console CLI.
* Default: 256 bytes
*/
#ifndef PJ_CLI_CONSOLE_POOL_SIZE
# define PJ_CLI_CONSOLE_POOL_SIZE 256
#endif
/**
* Pool increment size for console CLI.
* Default: 256 bytes
*/
#ifndef PJ_CLI_CONSOLE_POOL_INC
# define PJ_CLI_CONSOLE_POOL_INC 256
#endif
/**
* Initial pool size for telnet CLI.
* Default: 1024 bytes
*/
#ifndef PJ_CLI_TELNET_POOL_SIZE
# define PJ_CLI_TELNET_POOL_SIZE 1024
#endif
/**
* Pool increment size for telnet CLI.
* Default: 512 bytes
*/
#ifndef PJ_CLI_TELNET_POOL_INC
# define PJ_CLI_TELNET_POOL_INC 512
#endif
/**
* Maximum number of argument values of choice type.
* Default: 64
*/
#ifndef PJ_CLI_MAX_CHOICE_VAL
# define PJ_CLI_MAX_CHOICE_VAL 64
#endif
/**
* Maximum number of command history.
* Default: 16
*/
#ifndef PJ_CLI_MAX_CMD_HISTORY
# define PJ_CLI_MAX_CMD_HISTORY 16
#endif
/**
* @}
*/
#endif /* __PJLIB_UTIL_CONFIG_H__ */
@@ -0,0 +1,96 @@
/* $Id$ */
/*
* 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__ */
@@ -0,0 +1,461 @@
/* $Id$ */
/*
* 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);
/**
* Initialize DNS record as DNS AAAA record.
*
* @param rec The DNS resource record to be initialized as DNS
* AAAA 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_aaaa_rr(pj_dns_parsed_rr *rec,
const pj_str_t *res_name,
unsigned dnsclass,
unsigned ttl,
const pj_in6_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__ */
@@ -0,0 +1,117 @@
/* $Id$ */
/*
* 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__ */
@@ -0,0 +1,456 @@
/* $Id$ */
/*
* 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 */
/************************************************************
* JSON ERROR
***********************************************************/
/**
* @hideinitializer
* General invalid JSON message.
*/
#define PJLIB_UTIL_EINJSON (PJLIB_UTIL_ERRNO_START+30) /* 320030 */
/************************************************************
* 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 */
/************************************************************
* CLI ERROR
***********************************************************/
/**
* @hideinitializer
* End the current session. This is a special error code returned by
* pj_cli_sess_exec() to indicate that "exit" or equivalent command has been
* called to end the current session.
*/
#define PJ_CLI_EEXIT (PJLIB_UTIL_ERRNO_START+201)/* 320201 */
/**
* @hideinitializer
* A required CLI argument is not specified.
*/
#define PJ_CLI_EMISSINGARG (PJLIB_UTIL_ERRNO_START+202)/* 320202 */
/**
* @hideinitializer
* Too many CLI arguments.
*/
#define PJ_CLI_ETOOMANYARGS (PJLIB_UTIL_ERRNO_START+203)/* 320203 */
/**
* @hideinitializer
* Invalid CLI argument. Typically this is caused by extra characters
* specified in the command line which does not match any arguments.
*/
#define PJ_CLI_EINVARG (PJLIB_UTIL_ERRNO_START+204)/* 320204 */
/**
* @hideinitializer
* CLI command with the specified name already exist.
*/
#define PJ_CLI_EBADNAME (PJLIB_UTIL_ERRNO_START+205)/* 320205 */
/**
* @hideinitializer
* CLI command with the specified id already exist.
*/
#define PJ_CLI_EBADID (PJLIB_UTIL_ERRNO_START+206)/* 320206 */
/**
* @hideinitializer
* Invalid XML format for CLI command specification.
*/
#define PJ_CLI_EBADXML (PJLIB_UTIL_ERRNO_START+207)/* 320207 */
/**
* @hideinitializer
* CLI command entered by user match with more than one command/argument
* specification.
*/
#define PJ_CLI_EAMBIGUOUS (PJLIB_UTIL_ERRNO_START+208)/* 320208 */
/**
* @hideinitializer
* Telnet connection lost.
*/
#define PJ_CLI_ETELNETLOST (PJLIB_UTIL_ERRNO_START+211)/* 320211 */
/**
* @}
*/
#endif /* __PJLIB_UTIL_ERRNO_H__ */
@@ -0,0 +1,145 @@
/* $Id$ */
/* 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 */
@@ -0,0 +1,109 @@
/* $Id$ */
/*
* 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__ */
@@ -0,0 +1,107 @@
/* $Id$ */
/*
* 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__ */
@@ -0,0 +1,494 @@
/* $Id$ */
/*
* 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__ */
@@ -0,0 +1,228 @@
/* $Id$ */
/*
* Copyright (C) 2013 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_JSON_H__
#define __PJLIB_UTIL_JSON_H__
/**
* @file json.h
* @brief PJLIB JSON Implementation
*/
#include <pj/types.h>
#include <pj/list.h>
#include <pj/pool.h>
PJ_BEGIN_DECL
/**
* @defgroup PJ_JSON JSON Writer and Loader
* @ingroup PJ_FILE_FMT
* @{
* This API implements JSON file format according to RFC 4627. It can be used
* to parse, write, and manipulate JSON documents.
*/
/**
* Type of JSON value.
*/
typedef enum pj_json_val_type
{
PJ_JSON_VAL_NULL, /**< Null value (null) */
PJ_JSON_VAL_BOOL, /**< Boolean value (true, false) */
PJ_JSON_VAL_NUMBER, /**< Numeric (float or fixed point) */
PJ_JSON_VAL_STRING, /**< Literal string value. */
PJ_JSON_VAL_ARRAY, /**< Array */
PJ_JSON_VAL_OBJ /**< Object. */
} pj_json_val_type;
/* Forward declaration for JSON element */
typedef struct pj_json_elem pj_json_elem;
/**
* JSON list to store child elements.
*/
typedef struct pj_json_list
{
PJ_DECL_LIST_MEMBER(pj_json_elem);
} pj_json_list;
/**
* This represents JSON element. A JSON element is basically a name/value
* pair, where the name is a string and the value can be one of null, boolean
* (true and false constants), number, string, array (containing zero or more
* elements), or object. An object can be viewed as C struct, that is a
* compound element containing other elements, each having name/value pair.
*/
struct pj_json_elem
{
PJ_DECL_LIST_MEMBER(pj_json_elem);
pj_str_t name; /**< ELement name. */
pj_json_val_type type; /**< Element type. */
union
{
pj_bool_t is_true; /**< Boolean value. */
float num; /**< Number value. */
pj_str_t str; /**< String value. */
pj_json_list children; /**< Object and array children */
} value; /**< Element value. */
};
/**
* Structure to be specified to pj_json_parse() to be filled with additional
* info when parsing failed.
*/
typedef struct pj_json_err_info
{
unsigned line; /**< Line location of the error */
unsigned col; /**< Column location of the error */
int err_char; /**< The offending character. */
} pj_json_err_info;
/**
* Type of function callback to write JSON document in pj_json_writef().
*
* @param s The string to be written to the document.
* @param size The length of the string
* @param user_data User data that was specified to pj_json_writef()
*
* @return If the callback returns non-PJ_SUCCESS, it will
* stop the pj_json_writef() function and this error
* will be returned to caller.
*/
typedef pj_status_t (*pj_json_writer)(const char *s,
unsigned size,
void *user_data);
/**
* Initialize null element.
*
* @param el The element.
* @param name Name to be given to the element, or NULL.
*/
PJ_DECL(void) pj_json_elem_null(pj_json_elem *el, pj_str_t *name);
/**
* Initialize boolean element with the specified value.
*
* @param el The element.
* @param name Name to be given to the element, or NULL.
* @param val The value.
*/
PJ_DECL(void) pj_json_elem_bool(pj_json_elem *el, pj_str_t *name,
pj_bool_t val);
/**
* Initialize number element with the specified value.
*
* @param el The element.
* @param name Name to be given to the element, or NULL.
* @param val The value.
*/
PJ_DECL(void) pj_json_elem_number(pj_json_elem *el, pj_str_t *name,
float val);
/**
* Initialize string element with the specified value.
*
* @param el The element.
* @param name Name to be given to the element, or NULL.
* @param val The value.
*/
PJ_DECL(void) pj_json_elem_string(pj_json_elem *el, pj_str_t *name,
pj_str_t *val);
/**
* Initialize element as an empty array
*
* @param el The element.
* @param name Name to be given to the element, or NULL.
*/
PJ_DECL(void) pj_json_elem_array(pj_json_elem *el, pj_str_t *name);
/**
* Initialize element as an empty object
*
* @param el The element.
* @param name Name to be given to the element, or NULL.
*/
PJ_DECL(void) pj_json_elem_obj(pj_json_elem *el, pj_str_t *name);
/**
* Add an element to an object or array.
*
* @param el The object or array element.
* @param child Element to be added to the object or array.
*/
PJ_DECL(void) pj_json_elem_add(pj_json_elem *el, pj_json_elem *child);
/**
* Parse a JSON document in the buffer. The buffer MUST be NULL terminated,
* or if not then it must have enough size to put the NULL character.
*
* @param pool The pool to allocate memory for creating elements.
* @param buffer String buffer containing JSON document.
* @param size Size of the document.
* @param err_info Optional structure to be filled with info when
* parsing failed.
*
* @return The root element from the document.
*/
PJ_DECL(pj_json_elem*) pj_json_parse(pj_pool_t *pool,
char *buffer,
unsigned *size,
pj_json_err_info *err_info);
/**
* Write the specified element to the string buffer.
*
* @param elem The element to be written.
* @param buffer Output buffer.
* @param size On input, it must be set to the size of the buffer.
* Upon successful return, this will be set to
* the length of the written string.
*
* @return PJ_SUCCESS on success or the appropriate error.
*/
PJ_DECL(pj_status_t) pj_json_write(const pj_json_elem *elem,
char *buffer, unsigned *size);
/**
* Incrementally write the element to arbitrary medium using the specified
* callback to write the document chunks.
*
* @param elem The element to be written.
* @param writer Callback function which will be called to write
* text chunks.
* @param user_data Arbitrary user data which will be given back when
* calling the callback.
*
* @return PJ_SUCCESS on success or the appropriate error.
*/
PJ_DECL(pj_status_t) pj_json_writef(const pj_json_elem *elem,
pj_json_writer writer,
void *user_data);
/**
* @}
*/
PJ_END_DECL
#endif /* __PJLIB_UTIL_JSON_H__ */
@@ -0,0 +1,74 @@
/* $Id$ */
/*
* 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__ */
@@ -0,0 +1,196 @@
/* $Id$ */
/*
* 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__ */
@@ -0,0 +1,516 @@
/* $Id$ */
/*
* 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;
/**
* This structure represents DNS address record, i.e: DNS A and DNS AAAA
* records, as the result of parsing DNS response packet using
* #pj_dns_parse_addr_response().
*/
typedef struct pj_dns_addr_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 */
struct {
/** IP address family */
int af;
/** IP address */
union {
/** IPv4 address */
pj_in_addr v4;
/** IPv6 address */
pj_in6_addr v6;
} ip;
} addr[PJ_DNS_MAX_IP_IN_A_REC];
/** Internal buffer for hostname and alias. */
char buf_[128];
} pj_dns_addr_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);
/**
* A utility function to parse a DNS response containing AAAA records into
* DNS AAAA record.
*
* @param pkt The DNS response packet.
* @param rec The structure to be initialized with the parsed
* DNS AAAA record from the packet.
*
* @return PJ_SUCCESS if response can be parsed successfully.
*/
PJ_DECL(pj_status_t) pj_dns_parse_addr_response(
const pj_dns_parsed_packet *pkt,
pj_dns_addr_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__ */
@@ -0,0 +1,554 @@
/* $Id$ */
/*
* 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 be NULL terminated and have
* length at least buflen+1 (buflen MUST NOT include the NULL terminator).
*
* @param scanner The scanner to be initialized.
* @param bufstart The input buffer to scan, which must be NULL terminated.
* @param buflen The length of the input buffer, which normally is
* strlen(bufstart), hence not counting the NULL terminator.
* @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,
pj_size_t 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
@@ -0,0 +1,97 @@
/* $Id$ */
/*
* 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__ */
@@ -0,0 +1,84 @@
/* $Id$ */
/*
* 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__ */
@@ -0,0 +1,80 @@
/* $Id$ */
/*
* 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__ */
@@ -0,0 +1,222 @@
/* $Id$ */
/*
* 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 both DNS A and DNS AAAA
* resolutions if SRV 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_AAAA to
* make the resolver fallback to both DNS A and DNS AAAA
* resolutions if SRV resolution fails.
*/
PJ_DNS_SRV_FALLBACK_AAAA = 2,
/**
* Specify if the resolver should try to resolve with DNS AAAA
* resolution 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,
/**
* Specify if the resolver should try to resolve with DNS AAAA
* resolution only (i.e: without DNS A resolution) for each targets
* in the DNS SRV record.
*/
PJ_DNS_SRV_RESOLVE_AAAA_ONLY = 8
} 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_addr_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__ */
@@ -0,0 +1,102 @@
/* $Id$ */
/*
* 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__ */
@@ -0,0 +1,289 @@
/* $Id$ */
/*
* 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[]);
/*
* This structre describes configurable setting for requesting mapped address.
*/
typedef struct pjstun_setting
{
/**
* Specifies whether STUN request generated by old STUN library should
* insert magic cookie (specified in RFC 5389) in the transaction ID.
*/
pj_bool_t use_stun2;
/**
* Address family of the STUN servers.
*/
int af;
/**
* Host name or IP address string of the first STUN server.
*/
pj_str_t srv1;
/**
* The port number of the first STUN server.
*/
int port1;
/**
* Host name or IP address string of the second STUN server.
*/
pj_str_t srv2;
/**
* The port number of the second STUN server.
*/
int port2;
} pjstun_setting;
/**
* Another version of mapped address resolution of local sockets to multiple
* STUN servers configured in #pjstun_setting. 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 opt The STUN settings.
* @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 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_addr2( pj_pool_factory *pf,
const pjstun_setting *opt,
int sock_cnt,
pj_sock_t sock[],
pj_sockaddr_in mapped_addr[]);
PJ_END_DECL
/**
* @}
*/
#endif /* __PJSTUN_H__ */
@@ -0,0 +1,95 @@
/* $Id$ */
/*
* 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__ */
@@ -0,0 +1,249 @@
/* $Id$ */
/*
* 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.
*
* Note that the XML message input buffer MUST be NULL terminated and have
* length at least len+1 (len MUST NOT include the NULL terminator).
*
* @param pool Pool to allocate memory from.
* @param msg The XML message to parse, MUST be NULL terminated.
* @param len The length of the message, not including NULL terminator.
*
* @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__ */