235 ast_log(
LOG_NOTICE,
"PJSIP: Refusing outbound call to endpoint '%s': maintenance mode active\n",
256 pjsip_msg *msg = rdata->msg_info.msg;
257 const pjsip_method *
method = &msg->line.req.method;
259 pjsip_expires_hdr *expires_hdr;
263 pjsip_generic_int_hdr *retry_after;
264 static const pj_str_t str_retry_after = {
"Retry-After", 11 };
268 is_subscribe = pjsip_method_cmp(
method, pjsip_get_subscribe_method()) == 0;
269 is_register = pjsip_method_cmp(
method, pjsip_get_register_method()) == 0;
272 to = rdata->msg_info.to;
273 if (to->tag.slen > 0) {
278 if (is_subscribe || is_register) {
279 expires_hdr = pjsip_msg_find_hdr(msg, PJSIP_H_EXPIRES,
NULL);
280 if (expires_hdr && expires_hdr->ivalue == 0) {
297 ast_log(
LOG_NOTICE,
"PJSIP: Endpoint '%s' is in maintenance mode; rejecting new %.*s from %s\n",
300 rdata->pkt_info.src_name);
305 retry_after = pjsip_generic_int_hdr_create(rdata->tp_info.pool,
306 &str_retry_after, 300);
308 pj_list_push_back(&
hdr_list, retry_after);
318 .name = {
"Maintenance Module", 18 },
327 .priority = PJSIP_MOD_PRIORITY_APPLICATION - 3,
350 int wordlen = strlen(
word);
356 "endpoint",
word, wordlen);
380 const char *endpoint_name;
388 e->
command =
"pjsip set maintenance";
390 "Usage: pjsip set maintenance <on|off> <endpoint|all>\n"
391 " Place a PJSIP endpoint into or out of maintenance mode.\n"
392 " Use 'all' to toggle maintenance mode for every endpoint.\n"
393 " While in maintenance mode new inbound out-of-dialog requests\n"
394 " to that endpoint are rejected with 503 (except SUBSCRIBE/\n"
395 " REGISTER with Expires: 0), and outbound originations are\n"
400 static const char *
const opts[] = {
"on",
"off",
NULL };
404 if (!strncasecmp(
"all",
a->word, strlen(
a->word))) {
416 if (!strcasecmp(
a->argv[3],
"on")) {
418 }
else if (!strcasecmp(
a->argv[3],
"off")) {
424 endpoint_name =
a->argv[4];
426 if (!strcasecmp(endpoint_name,
"all")) {
428 if (!all_endpoints) {
429 ast_cli(
a->fd,
"Failed to retrieve endpoint list\n");
450 enable ?
"enabled" :
"disabled");
452 "(%d endpoint%s affected)\n",
453 enable ?
"enabled" :
"disabled",
454 count, count == 1 ?
"" :
"s");
456 ast_cli(
a->fd,
"Maintenance mode %s for %d endpoint%s%s\n",
457 enable ?
"ENABLED" :
"DISABLED",
458 count, count == 1 ?
"" :
"s",
459 failed ?
" (some failed)" :
"");
465 ast_cli(
a->fd,
"Endpoint '%s' not found\n", endpoint_name);
475 endpoint_name, enable ?
"enabled" :
"disabled");
477 enable ?
"enabled" :
"disabled", endpoint_name);
478 ast_cli(
a->fd,
"Maintenance mode %s for endpoint '%s'\n",
479 enable ?
"ENABLED" :
"DISABLED", endpoint_name);
480 }
else if (rc == 0 && enable) {
481 ast_cli(
a->fd,
"Endpoint '%s' is already in maintenance mode\n", endpoint_name);
482 }
else if (rc == 0) {
483 ast_cli(
a->fd,
"Endpoint '%s' was not in maintenance mode\n", endpoint_name);
485 ast_cli(
a->fd,
"Failed to %s maintenance mode for endpoint '%s'\n",
486 enable ?
"enable" :
"disable", endpoint_name);
497 const char *
name = obj;
498 int fd = *(
int *)arg;
506 const char *endpoint_name;
513 e->
command =
"pjsip show maintenance";
515 "Usage: pjsip show maintenance [endpoint]\n"
516 " Display endpoints currently in maintenance mode.\n"
517 " If [endpoint] is given, show the status for that endpoint only.\n";
527 endpoint_name =
a->argv[3];
530 ast_cli(
a->fd,
"Endpoint '%s' is in maintenance mode\n", endpoint_name);
533 ast_cli(
a->fd,
"Endpoint '%s' is NOT in maintenance mode\n", endpoint_name);
543 ast_cli(
a->fd,
" %-40s %s\n",
"Endpoint",
"State");
544 ast_cli(
a->fd,
" %-40s -----\n",
"----------------------------------------");
549 ast_cli(
a->fd,
"\n %d endpoint%s in maintenance mode\n\n",
550 count, count == 1 ?
"" :
"s");
564 const char *endpoint_name;
565 const char *state_str;
584 if (!strcasecmp(state_str,
"on")) {
586 }
else if (!strcasecmp(state_str,
"off")) {
593 if (!strcasecmp(endpoint_name,
"all")) {
597 if (!all_endpoints) {
614 enable ?
"enabled" :
"disabled");
616 "(%d endpoint%s affected)\n",
617 enable ?
"enabled" :
"disabled",
618 count, count == 1 ?
"" :
"s");
621 enable ?
"Maintenance mode enabled for all endpoints"
622 :
"Maintenance mode disabled for all endpoints");
636 enable ?
"enable" :
"disable", endpoint_name);
642 endpoint_name, enable ?
"enabled" :
"disabled");
644 enable ?
"enabled" :
"disabled", endpoint_name);
647 enable ?
"Maintenance mode enabled" :
"Maintenance mode disabled");
656 const char *
name = obj;
674 const char *endpoint_name;
694 endpoint_name, entry ?
"enabled" :
"disabled");
719 ast_log(
LOG_ERROR,
"res_pjsip_maintenance: failed to allocate maintenance set\n");
753 .
requires =
"res_pjsip,res_pjsip_session",
void ast_cli_unregister_multiple(void)
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdup(str)
A wrapper for strdup()
#define ao2_iterator_next(iter)
@ AO2_ALLOC_OPT_LOCK_RWLOCK
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_find(container, arg, flags)
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Standard Command Line Interface.
#define AST_CLI_DEFINE(fn, txt,...)
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
void ast_cli(int fd, const char *fmt,...)
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
void astman_send_error_va(struct mansession *s, const struct message *m, const char *fmt,...)
Send error in manager transaction (with va_args support)
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
void astman_append(struct mansession *s, const char *fmt,...)
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Support for logging to various files, console and syslog Configuration in file logger....
static struct ao2_container * endpoints
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define EVENT_FLAG_REPORTING
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
#define EVENT_FLAG_SYSTEM
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODULE_SUPPORT_EXTENDED
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
void ast_sip_unregister_service(pjsip_module *module)
struct ao2_container * ast_sip_get_endpoints(void)
Retrieve any endpoints available to sorcery.
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
@ AST_SIP_SUPPLEMENT_PRIORITY_FIRST
struct ast_sip_endpoint * ast_pjsip_rdata_get_endpoint(pjsip_rx_data *rdata)
Get the looked-up endpoint on an out-of dialog request or response.
struct ast_str * ast_sip_create_ami_event(const char *event, struct ast_sip_ami *ami)
Creates a string to store AMI event data in.
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
static char * handle_cli_pjsip_show_maintenance(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int ami_maint_entry_cb(void *obj, void *arg, int flags)
ao2_callback used to emit one PJSIPMaintenanceStatus AMI list entry
static char * cli_complete_endpoint(const char *word)
static struct pjsip_module maintenance_pjsip_mod
static int cli_maint_entry_cb(void *obj, void *arg, int flags)
ao2_callback used to print one maintenance entry to the CLI
static int maint_set_remove(const char *endpoint_name)
static int maint_session_create(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, const char *location, const char *request_user, struct ast_stream_topology *req_topology)
static int ami_set_maintenance(struct mansession *s, const struct message *m)
static struct ast_sip_session_supplement maintenance_session_supplement
static char * handle_cli_pjsip_set_maintenance(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static pj_bool_t maintenance_on_rx_request(pjsip_rx_data *rdata)
static int maint_set_add(const char *endpoint_name)
static int apply_maintenance_state(const char *endpoint_name, int enable)
static int load_module(void)
static struct ao2_container * maintenance_set
static struct ast_cli_entry cli_maintenance[]
static int unload_module(void)
static int ami_show_maintenance(struct mansession *s, const struct message *m)
static const struct ast_sorcery_observer endpoint_observer
static void maint_endpoint_deleted(const void *obj)
#define ast_sip_session_register_supplement(supplement)
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
Unregister a an supplement to SIP session processing.
Sorcery Data Access Layer API.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Remove an observer from a specific object type.
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Add an observer to a specific object type.
struct ao2_container * ast_sorcery_retrieve_by_prefix(const struct ast_sorcery *sorcery, const char *type, const char *prefix, const size_t prefix_len)
Retrieve multiple objects whose id begins with the specified prefix.
String manipulation functions.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
struct ao2_container * ast_str_container_alloc_options(enum ao2_alloc_opts opts, int buckets)
Allocates a hash container for bare strings.
int ast_str_container_add(struct ao2_container *str_container, const char *add)
Adds a string to a string container allocated by ast_str_container_alloc.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
descriptor for a cli entry.
An entity with which Asterisk communicates.
A supplement to SIP message processing.
int(* session_create)(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, const char *location, const char *request_user, struct ast_stream_topology *req_topology)
Called before an outgoing session is created.
Interface for a sorcery object type observer.
void(* deleted)(const void *object)
Callback for when an object is deleted.
Support for dynamic strings.
In case you didn't read that giant block of text above the mansession_session struct,...