Compare commits
9 Commits
Author | SHA1 | Date |
---|---|---|
Riza Sulistyo | b23df5e0d3 | |
Riza Sulistyo | e02d0df8f6 | |
Riza Sulistyo | f48b841e14 | |
Sauw Ming | f7aba2f98d | |
Sauw Ming | 722c821b5e | |
Sauw Ming | 3566ac6cd4 | |
Sauw Ming | b94730283e | |
Sauw Ming | f414b9411c | |
Sauw Ming | b9aa5df291 |
|
@ -27,9 +27,10 @@ export _LDFLAGS := $(subst /,$(HOST_PSEP),$(PJLIB_UTIL_LIB)) \
|
|||
#
|
||||
export PJLIB_UTIL_SRCDIR = ../src/pjlib-util
|
||||
export PJLIB_UTIL_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \
|
||||
base64.o crc32.o errno.o dns.o dns_dump.o dns_server.o \
|
||||
getopt.o hmac_md5.o hmac_sha1.o http_client.o md5.o pcap.o resolver.o \
|
||||
scanner.o sha1.o srv_resolver.o string.o stun_simple.o \
|
||||
base64.o cli.o cli_console.o cli_telnet.o crc32.o errno.o dns.o \
|
||||
dns_dump.o dns_server.o getopt.o hmac_md5.o hmac_sha1.o \
|
||||
http_client.o md5.o pcap.o resolver.o scanner.o sha1.o \
|
||||
srv_resolver.o string.o stun_simple.o \
|
||||
stun_simple_client.o xml.o
|
||||
export PJLIB_UTIL_CFLAGS += $(_CFLAGS)
|
||||
|
||||
|
|
|
@ -2768,6 +2768,18 @@
|
|||
RelativePath="..\src\pjlib-util\base64.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\pjlib-util\cli.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\pjlib-util\cli_console.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\pjlib-util\cli_telnet.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\pjlib-util\crc32.c"
|
||||
>
|
||||
|
@ -4713,6 +4725,22 @@
|
|||
RelativePath="..\include\pjlib-util\base64.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\include\pjlib-util\cli.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\include\pjlib-util\cli_console.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\include\pjlib-util\cli_imp.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\include\pjlib-util\cli_telnet.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\include\pjlib-util\config.h"
|
||||
>
|
||||
|
|
|
@ -0,0 +1,524 @@
|
|||
/* $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.
|
||||
*
|
||||
\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_arg_get_dyn_choice_val
|
||||
*/
|
||||
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_arg_get_dyn_choice_val) (pj_cli_dyn_choice_param *param);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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,
|
||||
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);
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* End the specified session, and destroy it to release all resources used
|
||||
* by the session.
|
||||
*
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @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.
|
||||
* @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_arg_get_dyn_choice_val 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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* Please also see 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,110 @@
|
|||
/* $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;
|
||||
|
||||
} 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 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Default port number for telnet daemon.
|
||||
*/
|
||||
#ifndef PJ_CLI_TELNET_PORT
|
||||
# define PJ_CLI_TELNET_PORT 23
|
||||
#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, int 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,120 @@
|
|||
/* $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 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.
|
||||
*
|
||||
* Default: empty (no password)
|
||||
*/
|
||||
pj_str_t passwd;
|
||||
|
||||
/**
|
||||
* Specify text message to be displayed to newly connected users.
|
||||
*
|
||||
* Default: empty
|
||||
*/
|
||||
pj_str_t welcome_msg;
|
||||
|
||||
/**
|
||||
* Specify text message as a prompt string to user.
|
||||
*
|
||||
* Default: empty
|
||||
*/
|
||||
pj_str_t prompt_str;
|
||||
|
||||
} 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,
|
||||
const pj_cli_telnet_cfg *param,
|
||||
pj_cli_front_end **p_fe);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
PJ_END_DECL
|
||||
|
||||
#endif /* __PJLIB_UTIL_CLI_TELNET_H__ */
|
|
@ -266,6 +266,106 @@
|
|||
# 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: 120
|
||||
*/
|
||||
#ifndef PJ_CLI_MAX_CMDBUF
|
||||
# define PJ_CLI_MAX_CMDBUF 120
|
||||
#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: 16
|
||||
*/
|
||||
#ifndef PJ_CLI_MAX_CHOICE_VAL
|
||||
# define PJ_CLI_MAX_CHOICE_VAL 16
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Maximum number of command history.
|
||||
* Default: 16
|
||||
*/
|
||||
#ifndef PJ_CLI_MAX_CMD_HISTORY
|
||||
# define PJ_CLI_MAX_CMD_HISTORY 16
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -386,6 +386,55 @@
|
|||
*/
|
||||
#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
|
||||
* Invalid XML format for CLI command specification.
|
||||
*/
|
||||
#define PJ_CLI_EBADXML (PJLIB_UTIL_ERRNO_START+206)/* 320206 */
|
||||
/**
|
||||
* @hideinitializer
|
||||
* CLI command entered by user match with more than one command/argument
|
||||
* specification.
|
||||
*/
|
||||
#define PJ_CLI_EAMBIGUOUS (PJLIB_UTIL_ERRNO_START+207)/* 320207 */
|
||||
/**
|
||||
* @hideinitializer
|
||||
* Telnet connection lost.
|
||||
*/
|
||||
#define PJ_CLI_ETELNETLOST (PJLIB_UTIL_ERRNO_START+211)/* 320211 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,449 @@
|
|||
/* $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
|
||||
*/
|
||||
|
||||
#include <pjlib-util/cli_imp.h>
|
||||
#include <pjlib-util/cli_console.h>
|
||||
#include <pj/assert.h>
|
||||
#include <pj/errno.h>
|
||||
#include <pj/log.h>
|
||||
#include <pj/os.h>
|
||||
#include <pj/pool.h>
|
||||
#include <pj/string.h>
|
||||
#include <pjlib-util/errno.h>
|
||||
|
||||
/**
|
||||
* This specify the state of output character parsing.
|
||||
*/
|
||||
typedef enum out_parse_state
|
||||
{
|
||||
OP_NORMAL,
|
||||
OP_TYPE,
|
||||
OP_SHORTCUT,
|
||||
OP_CHOICE
|
||||
} out_parse_state;
|
||||
|
||||
struct cli_console_fe
|
||||
{
|
||||
pj_cli_front_end base;
|
||||
pj_pool_t *pool;
|
||||
pj_cli_sess *sess;
|
||||
pj_thread_t *input_thread;
|
||||
pj_bool_t thread_quit;
|
||||
pj_sem_t *thread_sem;
|
||||
pj_cli_console_cfg cfg;
|
||||
|
||||
struct async_input_t
|
||||
{
|
||||
char *buf;
|
||||
unsigned maxlen;
|
||||
pj_sem_t *sem;
|
||||
} input;
|
||||
};
|
||||
|
||||
static void cli_console_write_log(pj_cli_front_end *fe, int level,
|
||||
const char *data, int len)
|
||||
{
|
||||
struct cli_console_fe * cfe = (struct cli_console_fe *)fe;
|
||||
|
||||
if (cfe->sess->log_level > level)
|
||||
printf("%.*s", len, data);
|
||||
}
|
||||
|
||||
static void cli_console_quit(pj_cli_front_end *fe, pj_cli_sess *req)
|
||||
{
|
||||
struct cli_console_fe * cfe = (struct cli_console_fe *)fe;
|
||||
|
||||
PJ_UNUSED_ARG(req);
|
||||
|
||||
pj_assert(cfe);
|
||||
if (cfe->input_thread) {
|
||||
cfe->thread_quit = PJ_TRUE;
|
||||
pj_sem_post(cfe->input.sem);
|
||||
pj_sem_post(cfe->thread_sem);
|
||||
}
|
||||
}
|
||||
|
||||
static void cli_console_destroy(pj_cli_front_end *fe)
|
||||
{
|
||||
struct cli_console_fe * cfe = (struct cli_console_fe *)fe;
|
||||
|
||||
pj_assert(cfe);
|
||||
cli_console_quit(fe, NULL);
|
||||
|
||||
if (cfe->input_thread)
|
||||
pj_thread_destroy(cfe->input_thread);
|
||||
pj_sem_destroy(cfe->thread_sem);
|
||||
pj_sem_destroy(cfe->input.sem);
|
||||
pj_pool_release(cfe->pool);
|
||||
}
|
||||
|
||||
PJ_DEF(void) pj_cli_console_cfg_default(pj_cli_console_cfg *param)
|
||||
{
|
||||
pj_assert(param);
|
||||
|
||||
param->log_level = PJ_CLI_CONSOLE_LOG_LEVEL;
|
||||
param->prompt_str.slen = 0;
|
||||
}
|
||||
|
||||
PJ_DEF(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)
|
||||
{
|
||||
pj_cli_sess *sess;
|
||||
struct cli_console_fe *fe;
|
||||
pj_cli_console_cfg cfg;
|
||||
pj_pool_t *pool;
|
||||
|
||||
PJ_ASSERT_RETURN(cli && p_sess, PJ_EINVAL);
|
||||
|
||||
pool = pj_pool_create(pj_cli_get_param(cli)->pf, "console_fe",
|
||||
PJ_CLI_CONSOLE_POOL_SIZE, PJ_CLI_CONSOLE_POOL_INC,
|
||||
NULL);
|
||||
if (!pool)
|
||||
return PJ_ENOMEM;
|
||||
sess = PJ_POOL_ZALLOC_T(pool, pj_cli_sess);
|
||||
fe = PJ_POOL_ZALLOC_T(pool, struct cli_console_fe);
|
||||
|
||||
if (!param) {
|
||||
pj_cli_console_cfg_default(&cfg);
|
||||
param = &cfg;
|
||||
}
|
||||
sess->fe = &fe->base;
|
||||
sess->log_level = param->log_level;
|
||||
sess->op = PJ_POOL_ZALLOC_T(pool, struct pj_cli_sess_op);
|
||||
fe->base.op = PJ_POOL_ZALLOC_T(pool, struct pj_cli_front_end_op);
|
||||
fe->base.cli = cli;
|
||||
fe->base.type = PJ_CLI_CONSOLE_FRONT_END;
|
||||
fe->base.op->on_write_log = &cli_console_write_log;
|
||||
fe->base.op->on_quit = &cli_console_quit;
|
||||
fe->base.op->on_destroy = &cli_console_destroy;
|
||||
fe->pool = pool;
|
||||
fe->sess = sess;
|
||||
pj_sem_create(pool, "console_fe", 0, 1, &fe->thread_sem);
|
||||
pj_sem_create(pool, "console_fe", 0, 1, &fe->input.sem);
|
||||
pj_cli_register_front_end(cli, &fe->base);
|
||||
|
||||
if (param->prompt_str.slen == 0) {
|
||||
pj_str_t prompt_sign = pj_str(">>> ");
|
||||
fe->cfg.prompt_str.ptr = pj_pool_alloc(fe->pool, prompt_sign.slen+1);
|
||||
pj_strcpy(&fe->cfg.prompt_str, &prompt_sign);
|
||||
} else {
|
||||
fe->cfg.prompt_str.ptr = pj_pool_alloc(fe->pool,
|
||||
param->prompt_str.slen+1);
|
||||
pj_strcpy(&fe->cfg.prompt_str, ¶m->prompt_str);
|
||||
}
|
||||
fe->cfg.prompt_str.ptr[fe->cfg.prompt_str.slen] = 0;
|
||||
|
||||
*p_sess = sess;
|
||||
if (p_fe)
|
||||
*p_fe = &fe->base;
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
static void send_prompt_str(pj_cli_sess *sess)
|
||||
{
|
||||
pj_str_t send_data;
|
||||
char data_str[128];
|
||||
struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe;
|
||||
|
||||
send_data.ptr = &data_str[0];
|
||||
send_data.slen = 0;
|
||||
|
||||
pj_strcat(&send_data, &fe->cfg.prompt_str);
|
||||
send_data.ptr[send_data.slen] = 0;
|
||||
|
||||
printf("%s", send_data.ptr);
|
||||
}
|
||||
|
||||
static void send_err_arg(pj_cli_sess *sess,
|
||||
const pj_cli_exec_info *info,
|
||||
const pj_str_t *msg,
|
||||
pj_bool_t with_return)
|
||||
{
|
||||
pj_str_t send_data;
|
||||
char data_str[256];
|
||||
unsigned len;
|
||||
unsigned i;
|
||||
struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe;
|
||||
|
||||
send_data.ptr = &data_str[0];
|
||||
send_data.slen = 0;
|
||||
|
||||
if (with_return)
|
||||
pj_strcat2(&send_data, "\r\n");
|
||||
|
||||
len = fe->cfg.prompt_str.slen + info->err_pos;
|
||||
|
||||
for (i=0;i<len;++i) {
|
||||
pj_strcat2(&send_data, " ");
|
||||
}
|
||||
pj_strcat2(&send_data, "^");
|
||||
pj_strcat2(&send_data, "\r\n");
|
||||
pj_strcat(&send_data, msg);
|
||||
pj_strcat(&send_data, &fe->cfg.prompt_str);
|
||||
|
||||
send_data.ptr[send_data.slen] = 0;
|
||||
printf("%s", send_data.ptr);
|
||||
}
|
||||
|
||||
static void send_inv_arg(pj_cli_sess *sess,
|
||||
const pj_cli_exec_info *info,
|
||||
pj_bool_t with_return)
|
||||
{
|
||||
static const pj_str_t ERR_MSG = {"%Error : Invalid Arguments\r\n", 28};
|
||||
send_err_arg(sess, info, &ERR_MSG, with_return);
|
||||
}
|
||||
|
||||
static void send_too_many_arg(pj_cli_sess *sess,
|
||||
const pj_cli_exec_info *info,
|
||||
pj_bool_t with_return)
|
||||
{
|
||||
static const pj_str_t ERR_MSG = {"%Error : Too Many Arguments\r\n", 29};
|
||||
send_err_arg(sess, info, &ERR_MSG, with_return);
|
||||
}
|
||||
|
||||
static void send_ambi_arg(pj_cli_sess *sess,
|
||||
const pj_cli_exec_info *info,
|
||||
pj_bool_t with_return)
|
||||
{
|
||||
unsigned i;
|
||||
pj_ssize_t j;
|
||||
unsigned len;
|
||||
pj_str_t send_data;
|
||||
char data[1028];
|
||||
struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe;
|
||||
const pj_cli_hint_info *hint = info->hint;
|
||||
out_parse_state parse_state = OP_NORMAL;
|
||||
pj_ssize_t max_length = 0;
|
||||
static const pj_str_t sc_type = {"sc", 2};
|
||||
static const pj_str_t choice_type = {"choice", 6};
|
||||
send_data.ptr = &data[0];
|
||||
send_data.slen = 0;
|
||||
|
||||
if (with_return)
|
||||
pj_strcat2(&send_data, "\r\n");
|
||||
|
||||
len = fe->cfg.prompt_str.slen + info->err_pos;
|
||||
|
||||
for (i=0;i<len;++i) {
|
||||
pj_strcat2(&send_data, " ");
|
||||
}
|
||||
pj_strcat2(&send_data, "^");
|
||||
|
||||
/* Get the max length of the command name */
|
||||
for (i=0;i<info->hint_cnt;++i) {
|
||||
if (hint[i].name.slen > max_length) {
|
||||
max_length = hint[i].name.slen;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0;i<info->hint_cnt;++i) {
|
||||
pj_strcat2(&send_data, "\r\n ");
|
||||
|
||||
if ((&hint[i].type) && (hint[i].type.slen > 0)) {
|
||||
if (pj_stricmp(&hint[i].type, &sc_type) == 0) {
|
||||
parse_state = OP_SHORTCUT;
|
||||
} else if (pj_stricmp(&hint[i].type, &choice_type) == 0) {
|
||||
parse_state = OP_CHOICE;
|
||||
} else {
|
||||
parse_state = OP_TYPE;
|
||||
}
|
||||
} else {
|
||||
parse_state = OP_NORMAL;
|
||||
}
|
||||
|
||||
switch (parse_state) {
|
||||
case OP_CHOICE:
|
||||
pj_strcat2(&send_data, "[");
|
||||
pj_strcat(&send_data, &hint[i].name);
|
||||
pj_strcat2(&send_data, "]");
|
||||
break;
|
||||
case OP_TYPE:
|
||||
pj_strcat2(&send_data, "<");
|
||||
pj_strcat(&send_data, &hint[i].type);
|
||||
pj_strcat2(&send_data, ">");
|
||||
break;
|
||||
default:
|
||||
pj_strcat(&send_data, &hint[i].name);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((&hint[i].desc) && (hint[i].desc.slen > 0)) {
|
||||
if (parse_state != OP_TYPE) {
|
||||
for (j=0;j<(max_length-hint[i].name.slen);++j) {
|
||||
pj_strcat2(&send_data, " ");
|
||||
}
|
||||
}
|
||||
pj_strcat2(&send_data, " ");
|
||||
pj_strcat(&send_data, &hint[i].desc);
|
||||
}
|
||||
}
|
||||
pj_strcat2(&send_data, "\r\n");
|
||||
pj_strcat(&send_data, &fe->cfg.prompt_str);
|
||||
|
||||
send_data.ptr[send_data.slen] = 0;
|
||||
printf("%s", send_data.ptr);
|
||||
}
|
||||
|
||||
static pj_bool_t handle_hint(pj_cli_sess *sess)
|
||||
{
|
||||
pj_status_t status;
|
||||
pj_bool_t retval = PJ_TRUE;
|
||||
|
||||
pj_pool_t *pool;
|
||||
pj_cli_cmd_val *cmd_val;
|
||||
pj_cli_exec_info info;
|
||||
struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe;
|
||||
char *recv_buf = fe->input.buf;
|
||||
pj_cli_t *cli = sess->fe->cli;
|
||||
|
||||
pool = pj_pool_create(pj_cli_get_param(cli)->pf, "handle_hint",
|
||||
PJ_CLI_CONSOLE_POOL_SIZE, PJ_CLI_CONSOLE_POOL_INC,
|
||||
NULL);
|
||||
|
||||
cmd_val = PJ_POOL_ZALLOC_T(pool, pj_cli_cmd_val);
|
||||
|
||||
status = pj_cli_sess_parse(sess, recv_buf, cmd_val,
|
||||
pool, &info);
|
||||
|
||||
switch (status) {
|
||||
case PJ_CLI_EINVARG:
|
||||
send_inv_arg(sess, &info, PJ_TRUE);
|
||||
break;
|
||||
case PJ_CLI_ETOOMANYARGS:
|
||||
send_too_many_arg(sess, &info, PJ_TRUE);
|
||||
break;
|
||||
case PJ_CLI_EMISSINGARG:
|
||||
case PJ_CLI_EAMBIGUOUS:
|
||||
send_ambi_arg(sess, &info, PJ_TRUE);
|
||||
break;
|
||||
case PJ_SUCCESS:
|
||||
if (info.hint_cnt > 0) {
|
||||
/* Compelete command */
|
||||
send_ambi_arg(sess, &info, PJ_TRUE);
|
||||
} else {
|
||||
retval = PJ_FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
pj_pool_release(pool);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static pj_bool_t handle_exec(pj_cli_sess *sess)
|
||||
{
|
||||
pj_status_t status;
|
||||
pj_bool_t retval = PJ_TRUE;
|
||||
|
||||
pj_pool_t *pool;
|
||||
pj_cli_exec_info info;
|
||||
pj_cli_t *cli = sess->fe->cli;
|
||||
struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe;
|
||||
char *recv_buf = fe->input.buf;
|
||||
|
||||
printf("\r\n");
|
||||
|
||||
pool = pj_pool_create(pj_cli_get_param(cli)->pf, "handle_exec",
|
||||
PJ_CLI_CONSOLE_POOL_SIZE, PJ_CLI_CONSOLE_POOL_INC,
|
||||
NULL);
|
||||
|
||||
status = pj_cli_sess_exec(sess, recv_buf,
|
||||
pool, &info);
|
||||
|
||||
switch (status) {
|
||||
case PJ_CLI_EINVARG:
|
||||
send_inv_arg(sess, &info, PJ_FALSE);
|
||||
break;
|
||||
case PJ_CLI_ETOOMANYARGS:
|
||||
send_too_many_arg(sess, &info, PJ_FALSE);
|
||||
break;
|
||||
case PJ_CLI_EAMBIGUOUS:
|
||||
case PJ_CLI_EMISSINGARG:
|
||||
send_ambi_arg(sess, &info, PJ_FALSE);
|
||||
break;
|
||||
case PJ_CLI_EEXIT:
|
||||
retval = PJ_FALSE;
|
||||
break;
|
||||
case PJ_SUCCESS:
|
||||
send_prompt_str(sess);
|
||||
break;
|
||||
}
|
||||
|
||||
pj_pool_release(pool);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int readline_thread(void * p)
|
||||
{
|
||||
struct cli_console_fe * fe = (struct cli_console_fe *)p;
|
||||
|
||||
printf("%s", fe->cfg.prompt_str.ptr);
|
||||
|
||||
while (!fe->thread_quit) {
|
||||
unsigned input_len = 0;
|
||||
char *recv_buf = fe->input.buf;
|
||||
pj_bool_t is_valid = PJ_TRUE;
|
||||
|
||||
fgets(recv_buf, fe->input.maxlen, stdin);
|
||||
input_len = pj_ansi_strlen(fe->input.buf);
|
||||
if ((input_len > 1) && (fe->input.buf[input_len-2] == '?')) {
|
||||
fe->input.buf[input_len-1] = 0;
|
||||
is_valid = handle_hint(fe->sess);
|
||||
} else {
|
||||
is_valid = handle_exec(fe->sess);
|
||||
}
|
||||
|
||||
pj_sem_post(fe->input.sem);
|
||||
pj_sem_wait(fe->thread_sem);
|
||||
}
|
||||
fe->input_thread = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pj_cli_console_process(pj_cli_sess *sess,
|
||||
char *buf,
|
||||
unsigned maxlen)
|
||||
{
|
||||
struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe;
|
||||
|
||||
PJ_ASSERT_RETURN(sess, PJ_EINVAL);
|
||||
|
||||
fe->input.buf = buf;
|
||||
fe->input.maxlen = maxlen;
|
||||
|
||||
if (!fe->input_thread) {
|
||||
pj_status_t status;
|
||||
|
||||
status = pj_thread_create(fe->pool, NULL, &readline_thread, fe,
|
||||
0, 0, &fe->input_thread);
|
||||
if (status != PJ_SUCCESS)
|
||||
return status;
|
||||
} else {
|
||||
/* Wake up readchar thread */
|
||||
pj_sem_post(fe->thread_sem);
|
||||
}
|
||||
|
||||
pj_sem_wait(fe->input.sem);
|
||||
|
||||
return (pj_cli_is_quitting(fe->base.cli)? PJ_CLI_EEXIT : PJ_SUCCESS);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -95,6 +95,15 @@ static const struct
|
|||
PJ_BUILD_ERR( PJLIB_UTIL_EHTTPINCHDR, "Incomplete response header received"),
|
||||
PJ_BUILD_ERR( PJLIB_UTIL_EHTTPINSBUF, "Insufficient buffer"),
|
||||
PJ_BUILD_ERR( PJLIB_UTIL_EHTTPLOST, "Connection lost"),
|
||||
|
||||
/* CLI */
|
||||
PJ_BUILD_ERR( PJ_CLI_EEXIT, "Exit current session"),
|
||||
PJ_BUILD_ERR( PJ_CLI_EMISSINGARG, "Missing argument"),
|
||||
PJ_BUILD_ERR( PJ_CLI_ETOOMANYARGS, "Too many arguments"),
|
||||
PJ_BUILD_ERR( PJ_CLI_EINVARG, "Invalid argument"),
|
||||
PJ_BUILD_ERR( PJ_CLI_EBADNAME, "Command name already exists"),
|
||||
PJ_BUILD_ERR( PJ_CLI_EBADXML, "Invalid XML format"),
|
||||
PJ_BUILD_ERR( PJ_CLI_ETELNETLOST, "Connection lost"),
|
||||
};
|
||||
#endif /* PJ_HAS_ERROR_STRING */
|
||||
|
||||
|
|
|
@ -535,6 +535,17 @@ PJ_IDECL(pj_str_t*) pj_strtrim( pj_str_t *str );
|
|||
*/
|
||||
PJ_DECL(char*) pj_create_random_string(char *str, pj_size_t length);
|
||||
|
||||
/**
|
||||
* Convert string to signed integer. The conversion will stop as
|
||||
* soon as non-digit character is found or all the characters have
|
||||
* been processed.
|
||||
*
|
||||
* @param str the string.
|
||||
*
|
||||
* @return the integer.
|
||||
*/
|
||||
PJ_DECL(long) pj_strtol(const pj_str_t *str);
|
||||
|
||||
/**
|
||||
* Convert string to unsigned integer. The conversion will stop as
|
||||
* soon as non-digit character is found or all the characters have
|
||||
|
|
|
@ -69,7 +69,7 @@ PJ_DEF(char*) pj_stristr(const pj_str_t *str, const pj_str_t *substr)
|
|||
|
||||
PJ_DEF(pj_str_t*) pj_strltrim( pj_str_t *str )
|
||||
{
|
||||
char *end = str->ptr + str->slen;
|
||||
char *end = str->ptr + str->slen;
|
||||
register char *p = str->ptr;
|
||||
while (p < end && pj_isspace(*p))
|
||||
++p;
|
||||
|
@ -109,6 +109,19 @@ PJ_DEF(char*) pj_create_random_string(char *str, pj_size_t len)
|
|||
return str;
|
||||
}
|
||||
|
||||
PJ_DEF(long) pj_strtol(const pj_str_t *str)
|
||||
{
|
||||
PJ_CHECK_STACK();
|
||||
|
||||
if (str->slen > 0 && (str->ptr[0] == '+' || str->ptr[0] == '-')) {
|
||||
pj_str_t s;
|
||||
|
||||
s.ptr = str->ptr + 1;
|
||||
s.slen = str->slen - 1;
|
||||
return (str->ptr[0] == '-'? -(long)pj_strtoul(&s) : pj_strtoul(&s));
|
||||
} else
|
||||
return pj_strtoul(str);
|
||||
}
|
||||
|
||||
PJ_DEF(unsigned long) pj_strtoul(const pj_str_t *str)
|
||||
{
|
||||
|
|
|
@ -60,6 +60,7 @@ BINDIR = ..\bin\samples\$(TARGET)
|
|||
|
||||
SAMPLES = $(BINDIR)\auddemo.exe \
|
||||
$(BINDIR)\aectest.exe \
|
||||
$(BINDIR)\clidemo.exe \
|
||||
$(BINDIR)\confsample.exe \
|
||||
$(BINDIR)\confbench.exe \
|
||||
$(BINDIR)\encdec.exe \
|
||||
|
|
|
@ -15,6 +15,7 @@ BINDIR := ../bin/samples/$(TARGET_NAME)
|
|||
|
||||
SAMPLES := auddemo \
|
||||
aectest \
|
||||
clidemo \
|
||||
confsample \
|
||||
encdec \
|
||||
httpdemo \
|
||||
|
|
|
@ -1597,6 +1597,10 @@
|
|||
RelativePath="..\src\samples\auddemo.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\samples\clidemo.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\samples\confbench.c"
|
||||
>
|
||||
|
|
|
@ -0,0 +1,261 @@
|
|||
/* $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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Sample CLI application
|
||||
*/
|
||||
#include <pjlib-util/cli.h>
|
||||
#include <pjlib-util/cli_imp.h>
|
||||
#include <pjlib-util/cli_console.h>
|
||||
#include <pjlib-util/cli_telnet.h>
|
||||
#include <pjlib-util/errno.h>
|
||||
#include <pjlib.h>
|
||||
|
||||
#define THIS_FILE "clidemo.c"
|
||||
|
||||
/* Set this to 1 if you want to let the system assign a port
|
||||
* for the CLI telnet daemon.
|
||||
* Default: 1
|
||||
*/
|
||||
#define USE_RANDOM_PORT 0
|
||||
|
||||
struct cmd_xml_t {
|
||||
char * xml;
|
||||
pj_cli_cmd_handler handler;
|
||||
};
|
||||
|
||||
/*
|
||||
* Declaration of system specific main loop, which will be defined in
|
||||
* a separate file.
|
||||
*/
|
||||
pj_status_t app_main(pj_cli_t *cli);
|
||||
|
||||
#define print_msg(arg) \
|
||||
do { \
|
||||
unsigned d = pj_log_get_decor(); \
|
||||
pj_log_set_decor(0); \
|
||||
PJ_LOG(1, arg); \
|
||||
pj_log_set_decor(d); \
|
||||
} while (0)
|
||||
|
||||
static pj_cli_t *cli = NULL;
|
||||
|
||||
/* Handler for sayhello command */
|
||||
static pj_status_t sayhello(pj_cli_cmd_val *cval)
|
||||
{
|
||||
print_msg(("", "Hello %.*s!\r\n",
|
||||
(int)cval->argv[1].slen, cval->argv[1].ptr));
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
/* Handler for saybye command */
|
||||
static pj_status_t saybye(pj_cli_cmd_val *cval)
|
||||
{
|
||||
print_msg(("", "Bye %.*s!\r\n",
|
||||
(int)cval->argv[1].slen, cval->argv[1].ptr));
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
/* Handler for say command */
|
||||
static pj_status_t say(pj_cli_cmd_val *cval)
|
||||
{
|
||||
print_msg(("", "%.*s %.*s\r\n",
|
||||
(int)cval->argv[1].slen, cval->argv[1].ptr,
|
||||
(int)cval->argv[2].slen, cval->argv[2].ptr));
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
static pj_status_t quit_app(pj_cli_cmd_val *cval)
|
||||
{
|
||||
PJ_UNUSED_ARG(cval);
|
||||
pj_cli_quit(cval->sess->fe->cli, cval->sess, PJ_FALSE);
|
||||
|
||||
return PJ_CLI_EEXIT;
|
||||
}
|
||||
|
||||
static void get_codec_list(pj_cli_dyn_choice_param *param)
|
||||
{
|
||||
if (param->arg_id == 3) {
|
||||
param->cnt = 2;
|
||||
pj_strdup2(param->pool, ¶m->choice[0].value, "iLbc");
|
||||
pj_strdup2(param->pool, ¶m->choice[0].desc, "iLbc Codec");
|
||||
pj_strdup2(param->pool, ¶m->choice[1].value, "g729");
|
||||
pj_strdup2(param->pool, ¶m->choice[1].desc, "g729 Codec");
|
||||
}
|
||||
}
|
||||
|
||||
static struct cmd_xml_t cmd_xmls[] = {
|
||||
{"<CMD name='sayhello' id='1' sc=' ,h , ,, sh ,' desc='Will say hello'>"
|
||||
" <ARG name='whom' type='text' desc='Whom to say hello to'/>"
|
||||
"</CMD>",
|
||||
&sayhello},
|
||||
{"<CMD name='saybye' id='2' sc='b,sb' desc='Will say bye'>"
|
||||
" <ARG name='whom' type='text' desc='Whom to say bye to'/>"
|
||||
"</CMD>",
|
||||
&saybye},
|
||||
{"<CMD name='saymsg' id='3' sc='s' desc='Will say something'>"
|
||||
" <ARG name='msg' type='text' desc='Message to say'/>"
|
||||
" <ARG name='whom' type='text' desc='Whom to say to'/>"
|
||||
"</CMD>",
|
||||
&say},
|
||||
{"<CMD name='vid' id='1' desc='Video Command'>"
|
||||
" <CMD name='help' id='2' desc='Show Help' />"
|
||||
" <CMD name='enable' id='3' desc='Enable Video' />"
|
||||
" <CMD name='disable' id='4' desc='Disable Video' />"
|
||||
" <CMD name='call' id='5' desc='Video call' >"
|
||||
" <CMD name='add' id='6' desc='Add Call' />"
|
||||
" <CMD name='cap' id='7' desc='Capture Call' >"
|
||||
" <ARG name='streamno' type='int' desc='Stream Number' id='1'/>"
|
||||
" <ARG name='devid' type='int' desc='Device Id' optional='1' id='2'/>"
|
||||
" </CMD>"
|
||||
" </CMD>"
|
||||
"</CMD>",
|
||||
NULL},
|
||||
{"<CMD name='disable_codec' id='8' desc='Disable codec'>"
|
||||
" <ARG name='codec_list' type='choice' id='3' desc='Codec list'>"
|
||||
" <CHOICE value='g711' desc='G711 Codec'/>"
|
||||
" <CHOICE value='g722' desc='G722 Codec'/>"
|
||||
" </ARG>"
|
||||
"</CMD>",
|
||||
NULL},
|
||||
{"<CMD name='quit_app' id='999' sc='qa' desc='Quit the application'>"
|
||||
"</CMD>",
|
||||
&quit_app},
|
||||
};
|
||||
|
||||
static void log_writer(int level, const char *buffer, int len)
|
||||
{
|
||||
if (cli)
|
||||
pj_cli_write_log(cli, level, buffer, len);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
pj_caching_pool cp;
|
||||
pj_cli_cfg cli_cfg;
|
||||
pj_cli_telnet_cfg tcfg;
|
||||
pj_str_t xml;
|
||||
pj_status_t status;
|
||||
int i;
|
||||
|
||||
pj_init();
|
||||
pj_caching_pool_init(&cp, NULL, 0);
|
||||
pjlib_util_init();
|
||||
|
||||
/*
|
||||
* Create CLI app.
|
||||
*/
|
||||
pj_cli_cfg_default(&cli_cfg);
|
||||
cli_cfg.pf = &cp.factory;
|
||||
cli_cfg.name = pj_str("mycliapp");
|
||||
cli_cfg.title = pj_str("My CLI Application");
|
||||
|
||||
status = pj_cli_create(&cli_cfg, &cli);
|
||||
if (status != PJ_SUCCESS)
|
||||
goto on_return;
|
||||
|
||||
/*
|
||||
* Register some commands.
|
||||
*/
|
||||
for (i = 0; i < sizeof(cmd_xmls)/sizeof(cmd_xmls[0]); i++) {
|
||||
xml = pj_str(cmd_xmls[i].xml);
|
||||
status = pj_cli_add_cmd_from_xml(cli, NULL, &xml,
|
||||
cmd_xmls[i].handler, NULL, get_codec_list);
|
||||
if (status != PJ_SUCCESS)
|
||||
goto on_return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start telnet daemon
|
||||
*/
|
||||
pj_cli_telnet_cfg_default(&tcfg);
|
||||
// tcfg.passwd = pj_str("pjsip");
|
||||
#if USE_RANDOM_PORT
|
||||
tcfg.port = 0;
|
||||
#endif
|
||||
tcfg.port = 2233;
|
||||
tcfg.prompt_str = pj_str("CoolWater% ");
|
||||
status = pj_cli_telnet_create(cli, &tcfg, NULL);
|
||||
if (status != PJ_SUCCESS)
|
||||
goto on_return;
|
||||
|
||||
/*
|
||||
* Run the system specific main loop.
|
||||
*/
|
||||
status = app_main(cli);
|
||||
|
||||
on_return:
|
||||
|
||||
/*
|
||||
* Destroy
|
||||
*/
|
||||
pj_cli_destroy(cli);
|
||||
cli = NULL;
|
||||
pj_caching_pool_destroy(&cp);
|
||||
pj_shutdown();
|
||||
|
||||
return (status != PJ_SUCCESS ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
/*xxxxxxxxxxxxxxxxxxxxxxxxxxxxx main_console.c xxxxxxxxxxxxxxxxxxxxxxxxxxxx */
|
||||
/*
|
||||
* Simple implementation of app_main() for console targets
|
||||
*/
|
||||
pj_status_t app_main(pj_cli_t *cli)
|
||||
{
|
||||
pj_status_t status;
|
||||
pj_cli_sess *sess;
|
||||
pj_cli_console_cfg console_cfg;
|
||||
|
||||
pj_cli_console_cfg_default(&console_cfg);
|
||||
console_cfg.prompt_str = pj_str("HotWater> ");
|
||||
|
||||
/*
|
||||
* Create the console front end
|
||||
*/
|
||||
status = pj_cli_console_create(cli, &console_cfg, &sess, NULL);
|
||||
if (status != PJ_SUCCESS)
|
||||
return status;
|
||||
|
||||
pj_log_set_log_func(&log_writer);
|
||||
|
||||
/*
|
||||
* Main loop.
|
||||
*/
|
||||
for (;;) {
|
||||
char cmdline[PJ_CLI_MAX_CMDBUF];
|
||||
pj_status_t status;
|
||||
|
||||
status = pj_cli_console_process(sess, &cmdline[0], sizeof(cmdline));
|
||||
if (status != PJ_SUCCESS)
|
||||
break;
|
||||
|
||||
//pj_ansi_strcpy(cmdline, "sayhello {Teluu Inc.}");
|
||||
if (status == PJ_CLI_EEXIT) {
|
||||
/* exit is called */
|
||||
break;
|
||||
} else if (status != PJ_SUCCESS) {
|
||||
/* Something wrong with the cmdline */
|
||||
PJ_PERROR(1,(THIS_FILE, status, "Exec error"));
|
||||
}
|
||||
}
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
Loading…
Reference in New Issue