86 pjsip_expires_hdr *expires;
91 expiration = contact->expires;
92 }
else if ((expires = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES,
NULL))) {
94 expiration = expires->ivalue;
103 if (expiration < aor->minimum_expiration) {
125 pjsip_uri *contact_uri;
131 contact_uri = pjsip_parse_uri(details->
pool, (
char*)contact->
uri, strlen(contact->
uri), 0);
137 return (pjsip_uri_cmp(PJSIP_URI_IN_CONTACT_HDR, details->
uri, contact_uri) == PJ_SUCCESS) ?
CMP_MATCH : 0;
142 struct ast_sip_aor *aor,
int permanent,
int *added,
int *updated,
int *deleted)
144 pjsip_contact_hdr *previous =
NULL;
145 pjsip_contact_hdr *
contact = (pjsip_contact_hdr *)&rdata->msg_info.msg->hdr;
150 for (; (
contact = (pjsip_contact_hdr *) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT,
contact->next)); pj_pool_reset(
pool)) {
157 if (expiration != 0 || previous) {
164 }
else if (previous && previous->star) {
170 if (!PJSIP_URI_SCHEME_IS_SIP(
contact->uri) && !PJSIP_URI_SCHEME_IS_SIPS(
contact->uri)) {
174 details.uri = pjsip_uri_get_uri(
contact->uri);
177 if (pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, details.uri, contact_uri,
sizeof(contact_uri)) < 0) {
194 }
else if (expiration) {
226 pjsip_tx_data *tdata = arg;
230 pj_strdup2_with_null(tdata->pool, &uri, contact->
uri);
231 parsed = pjsip_parse_uri(tdata->pool, uri.ptr, uri.slen, PJSIP_PARSE_URI_AS_NAMEADDR);
233 if (parsed && (PJSIP_URI_SCHEME_IS_SIP(parsed) || PJSIP_URI_SCHEME_IS_SIPS(parsed))) {
234 pjsip_contact_hdr *hdr = pjsip_contact_hdr_create(tdata->pool);
241 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) hdr);
244 (
int) uri.slen, uri.ptr, contact->
aor);
254 pjsip_generic_string_hdr *path_hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &path_hdr_name,
NULL);
265 ast_str_set(path_str, 0,
"%.*s", (
int)path_hdr->hvalue.slen, path_hdr->hvalue.ptr);
267 while ((path_hdr = (pjsip_generic_string_hdr *) pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &path_hdr_name, path_hdr->next))) {
268 ast_str_append(path_str, 0,
",%.*s", (
int)path_hdr->hvalue.slen, path_hdr->hvalue.ptr);
276 const pj_str_t path_supported_name = {
"path", 4 };
277 pjsip_supported_hdr *supported_hdr;
292 supported_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_SUPPORTED,
NULL);
293 if (!supported_hdr) {
298 for (i = 0; i < supported_hdr->count; i++) {
299 if (!pj_stricmp(&supported_hdr->values[i], &path_supported_name)) {
413 aor_size = aor_name ? strlen(aor_name) : 0;
416 size_t contact_name_len = strlen(contact_name) + 1;
418 sizeof(*monitor) + 1 + aor_size + contact_name_len);
420 strcpy(monitor->
aor_name, aor_name);
442 const char *reason =
"none";
446 reason =
"registration failure";
449 reason =
"remove existing";
452 reason =
"expiration";
462 ast_verb(3,
"Removed contact '%s' from AOR '%s' due to %s\n",
463 contact->
uri, aor_name, reason);
492 struct excess_contact_vector *contact_vec = arg;
524 unsigned int to_remove)
526 struct excess_contact_vector contact_vec;
549 while (to_remove--) {
587 const char *aor_name,
591 static const pj_str_t USER_AGENT = {
"User-Agent", 10 };
599 pjsip_contact_hdr *contact_hdr = (pjsip_contact_hdr *)&rdata->msg_info.msg->hdr;
601 pjsip_tx_data *tdata;
605 pjsip_user_agent_hdr *user_agent_hdr;
606 pjsip_expires_hdr *expires_hdr;
607 pjsip_via_hdr *via_hdr;
608 pjsip_via_hdr *via_hdr_last;
611 pjsip_cid_hdr *call_id_hdr;
617 "Contact Comparison", 1024, 256);
619 response->code = 500;
626 if (
aor->permanent_contacts) {
635 response->code = 400;
642 ast_log(
LOG_WARNING,
"Invalid modifications made to REGISTER request from '%s' by intervening proxy\n",
644 response->code = 420;
649 if (
aor->remove_existing) {
651 contact_count =
MAX(updated + added - deleted, 0);
658 if (!existing_contacts) {
659 response->code = 500;
669 if (contact_count >
aor->max_contacts) {
672 ast_log(
LOG_WARNING,
"Registration attempt from endpoint '%s' (%s:%d) to AOR '%s' will exceed max contacts of %u\n",
674 aor_name,
aor->max_contacts);
675 response->code = 403;
681 user_agent_hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &USER_AGENT,
NULL);
682 if (user_agent_hdr) {
683 alloc_size = pj_strlen(&user_agent_hdr->hvalue) + 1;
689 via_hdr = via_hdr_last = (pjsip_via_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_VIA,
NULL);
692 while ( (via_hdr = (pjsip_via_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg,
693 PJSIP_H_VIA, via_hdr->next)) !=
NULL) {
694 via_hdr_last = via_hdr;
696 alloc_size = pj_strlen(&via_hdr_last->sent_by.host) + 1;
699 via_port=via_hdr_last->sent_by.port;
702 call_id_hdr = (pjsip_cid_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CALL_ID,
NULL);
704 alloc_size = pj_strlen(&call_id_hdr->id) + 1;
710 for (; (contact_hdr = (pjsip_contact_hdr *) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, contact_hdr->next)); pj_pool_reset(details.pool)) {
715 if (contact_hdr->star) {
722 if (existing_contacts) {
723 ao2_ref(existing_contacts, -1);
724 existing_contacts =
NULL;
729 if (!PJSIP_URI_SCHEME_IS_SIP(contact_hdr->uri) && !PJSIP_URI_SCHEME_IS_SIPS(contact_hdr->uri)) {
735 details.uri = pjsip_uri_get_uri(contact_hdr->uri);
736 pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, details.uri, contact_uri,
sizeof(contact_uri));
743 if (
contact && existing_contacts) {
752 ast_verb(3,
"Attempted to remove non-existent contact '%s' from AOR '%s' by request\n",
753 contact_uri, aor_name);
762 user_agent, via_addr, via_port, call_id, prune_on_boot,
endpoint);
765 contact_uri, aor_name);
770 size_t contact_name_len;
771 const char *contact_name;
779 contact_name_len = strlen(contact_name) + 1;
781 + contact_name_len, NULL);
793 ast_verb(3,
"Added contact '%s' to AOR '%s' with expiration of %d seconds\n",
806 }
else if (expiration) {
810 if (!contact_update) {
811 ast_log(
LOG_ERROR,
"Failed to update contact '%s' expiration time to %d seconds.\n",
830 ast_log(
LOG_ERROR,
"Failed to update contact '%s' expiration time to %d seconds.\n",
836 ast_debug(3,
"Refreshed contact '%s' on AOR '%s' with new expiration of %d seconds\n",
837 contact_uri, aor_name, expiration);
866 if (
aor->remove_existing && existing_contacts) {
869 if (contact_count >
aor->max_contacts) {
873 ao2_ref(existing_contacts, -1);
882 response->code = 500;
892 if ((expires_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES,
NULL))) {
894 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)expires_hdr);
897 response->tdata = tdata;
903 const char *aor_name)
924 if (response.
tdata) {
933 static int match_aor(
const char *aor_name,
const char *
id)
939 if (!strcmp(aor_name,
id)) {
940 ast_debug(3,
"Matched id '%s' to aor '%s'\n",
id, aor_name);
947 static char *
find_aor_name(
const pj_str_t *pj_username,
const pj_str_t *pj_domain,
const char *aors)
949 char *configured_aors;
957 username =
ast_alloca(pj_strlen(pj_username) + 1);
959 domain =
ast_alloca(pj_strlen(pj_domain) + 1);
962 id_domain =
ast_alloca(strlen(username) + strlen(domain) + 2);
963 sprintf(id_domain,
"%s@%s", username, domain);
968 configured_aors = aors_buf;
978 char *id_domain_alias =
ast_alloca(strlen(username) + strlen(alias->
domain) + 2);
980 sprintf(id_domain_alias,
"%s@%s", username, alias->
domain);
983 configured_aors = strcpy(aors_buf, aors);
985 if (
match_aor(aor_name, id_domain_alias)) {
997 configured_aors = strcpy(aors_buf, aors);
1010 char *aor_name =
NULL;
1020 uri = pjsip_uri_get_uri(rdata->msg_info.to->uri);
1022 pj_strassign(&username, &uri->user);
1031 pj_ssize_t semi = pj_strcspn2(&username,
";");
1032 if (semi < pj_strlen(&username)) {
1033 username.slen = semi;
1039 ast_debug(3,
"Matched aor '%s' by To username\n", aor_name);
1043 while ((header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_AUTHORIZATION,
1044 header ? header->next :
NULL))) {
1045 if (header && !pj_stricmp2(&header->scheme,
"digest")) {
1046 aor_name =
find_aor_name(&header->credential.digest.username,
1047 &header->credential.digest.realm, endpoint->
aors);
1049 ast_debug(3,
"Matched aor '%s' by Authentication username\n", aor_name);
1070 rdata->pkt_info.src_name, rdata->pkt_info.src_port);
1081 const char *aor_name;
1083 if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_register_method) || !endpoint) {
1092 rdata->pkt_info.src_name, rdata->pkt_info.src_port);
1096 if (!PJSIP_URI_SCHEME_IS_SIP(rdata->msg_info.to->uri) && !PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.to->uri)) {
1100 rdata->pkt_info.src_name, rdata->pkt_info.src_port);
1116 ast_log(
LOG_WARNING,
"AOR '%s' has no configured max_contacts. Endpoint '%s' (%s:%d) unable to register\n",
1118 rdata->pkt_info.src_name, rdata->pkt_info.src_port);
1200 "registration",
"start");
1225 #define AMI_SHOW_REGISTRATION_CONTACT_STATUSES "PJSIPShowRegistrationInboundContactStatuses" 1226 #define AMI_SHOW_REGISTRATIONS "PJSIPShowRegistrationsInbound" 1229 .name = {
"Registrar", 9 },
1231 .priority = PJSIP_MOD_PRIORITY_APPLICATION,
1270 char *time = alloca(64);
1272 while (check_interval) {
1273 sleep(check_interval);
1275 sprintf(time,
"%ld",
ast_tvnow().tv_sec);
1278 ast_debug(4,
"Woke up at %s Interval: %d\n", time, check_interval);
1299 if (check_interval) {
1302 ast_log(
LOG_ERROR,
"Could not create thread for checking contact expiration.\n");
1305 ast_debug(3,
"Interval = %d, starting thread\n", check_interval);
1309 pthread_kill(check_thread, SIGURG);
1310 pthread_join(check_thread,
NULL);
1312 ast_debug(3,
"Interval = 0, shutting thread down\n");
1324 const pj_str_t STR_REGISTER = {
"REGISTER", 8 };
1354 pthread_kill(check_thread, SIGURG);
1355 pthread_join(check_thread,
NULL);
1374 .requires =
"res_pjproject,res_pjsip",
static int load_module(void)
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
#define AST_VECTOR_ADD_SORTED(vec, elem, cmp)
Add an element into a sorted vector.
AST_VECTOR(excess_contact_vector, struct ast_sip_contact *)
static pthread_t check_thread
Thread keeping things alive.
static pj_bool_t registrar_on_rx_request(struct pjsip_rx_data *rdata)
void astman_append(struct mansession *s, const char *fmt,...)
Asterisk main include file. File version handling, generic pbx functions.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg)
For every aor in the comma separated aors string call the given 'on_aor' handler. ...
struct ao2_container * ast_sip_location_retrieve_aor_contacts_nolock(const struct ast_sip_aor *aor)
Retrieve all contacts currently available for an AOR without locking the AOR.
static int registrar_delete_contact(void *obj, void *arg, int flags)
Internal function used to delete a contact from an AOR.
static int register_aor(pjsip_rx_data *rdata, struct ast_sip_endpoint *endpoint, struct ast_sip_aor *aor, const char *aor_name)
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
static int registrar_add_non_permanent(void *obj, void *arg, int flags)
Callback function which adds non-permanent contacts to a container.
unsigned int max_contacts
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
static int match_aor(const char *aor_name, const char *id)
static int build_path_data(pjsip_rx_data *rdata, struct ast_str **path_str)
static char * find_aor_name(const pj_str_t *pj_username, const pj_str_t *pj_domain, const char *aors)
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
static int pjsip_max_url_size
#define ao2_callback(c, flags, cb_fn, arg)
#define VERBOSITY_ATLEAST(level)
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Structure for variables, used for configurations and for channel variables.
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Perform no matching, return all objects.
static int unload_module(void)
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
static int registrar_find_contact(void *obj, void *arg, int flags)
Callback function for finding a contact.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
static unsigned int registrar_get_expiration(const struct ast_sip_aor *aor, const pjsip_contact_hdr *contact, const pjsip_rx_data *rdata)
Internal function which returns the expiration time for a contact.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Return all matching objects.
static int contact_transport_monitor_matcher(void *a, void *b)
int ast_pjproject_get_buildopt(char *option, char *format_string,...)
Retrieve a pjproject build option.
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
#define ast_strdup(str)
A wrapper for strdup()
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
static void remove_excess_contacts(struct ao2_container *contacts, struct ao2_container *response_contacts, unsigned int to_remove)
int ast_sip_contact_to_str(void *object, void *arg, int flags)
Handler used to convert a contact to a string.
static int vec_contact_cmp(struct ast_sip_contact *left, struct ast_sip_contact *right)
#define ast_verb(level,...)
static int ami_show_registration_contact_statuses(struct mansession *s, const struct message *m)
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
#define ast_strlen_zero(foo)
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
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.
static int ami_registrations_aor(void *obj, void *arg, int flags)
#define ast_pthread_create_background(a, b, c, d)
const char * ast_config_AST_SYSTEM_NAME
int ast_sip_create_response(const pjsip_rx_data *rdata, int st_code, struct ast_sip_contact *contact, pjsip_tx_data **p_tdata)
General purpose method for creating a SIP response.
static void register_aor_core(pjsip_rx_data *rdata, struct ast_sip_endpoint *endpoint, struct ast_sip_aor *aor, const char *aor_name, struct ao2_container *contacts, struct aor_core_response *response)
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
#define EVENT_FLAG_SYSTEM
#define ast_debug(level,...)
Log a DEBUG message.
void ast_sip_report_failed_acl(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, const char *name)
Send a security event notification for when an ACL check fails.
struct ast_sip_identify_by_vector ident_method_order
void ast_sip_report_req_no_support(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, const char *req_type)
Send a security event notification for when a request is not supported.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Asterisk file paths, configured in asterisk.conf.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
struct ast_sip_contact * ast_sip_location_create_contact(struct ast_sip_aor *aor, const char *uri, struct timeval expiration_time, const char *path_info, const char *user_agent, const char *via_addr, int via_port, const char *call_id, int prune_on_boot, struct ast_sip_endpoint *endpoint)
Create a new contact for an AOR without locking the AOR.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define AST_PTHREADT_NULL
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
static struct ao2_container * endpoints
#define ao2_ref(o, delta)
In case you didn't read that giant block of text above the mansession_session struct, the struct mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
int ast_sip_send_stateful_response(pjsip_rx_data *rdata, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
Send a stateful response to an out of dialog request.
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
#define ast_strdupa(s)
duplicate a string in memory from the stack
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
struct ao2_container * container
static int ami_show_registrations(struct mansession *s, const struct message *m)
#define ast_variable_new(name, value, filename)
An entity with which Asterisk communicates.
unsigned int support_path
static void expiration_global_loaded(const char *object_type)
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
static int registrar_validate_path(pjsip_rx_data *rdata, struct ast_sip_aor *aor, struct ast_str **path_str)
static int ami_registrations_endpoint(void *obj, void *arg, int flags)
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.
int ast_sip_location_delete_contact(struct ast_sip_contact *contact)
Delete a contact.
void ast_sip_transport_monitor_unregister(pjsip_transport *transport, ast_transport_monitor_shutdown_cb cb, void *data, ast_transport_monitor_data_matcher matches)
Unregister a reliable transport shutdown monitor.
#define ast_test_suite_event_notify(s, f,...)
struct ast_sip_aor * ast_sip_location_retrieve_aor(const char *aor_name)
Retrieve a named AOR.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
static struct ast_sip_aor * find_registrar_aor(struct pjsip_rx_data *rdata, struct ast_sip_endpoint *endpoint)
enum ast_transport_monitor_reg ast_sip_transport_monitor_register_replace(pjsip_transport *transport, ast_transport_monitor_shutdown_cb cb, void *ao2_data, ast_transport_monitor_data_matcher matches)
Register a reliable transport shutdown monitor callback replacing any duplicate.
static int ami_registrations_endpoints(void *arg)
static int register_contact_transport_remove_cb(void *data)
static int vec_contact_add(void *obj, void *arg, int flags)
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compres two struct timeval instances returning -1, 0, 1 if the first arg is smaller, equal or greater to the second.
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
#define ao2_unlink(container, obj)
#define AMI_SHOW_REGISTRATIONS
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
static void register_contact_transport_shutdown_cb(void *data)
Interface for a sorcery object type observer.
static unsigned int monitor
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
#define ao2_iterator_next(iter)
#define ao2_alloc(data_size, destructor_fn)
void ast_sip_add_date_header(pjsip_tx_data *tdata)
Adds a Date header to the tdata, formatted like: Date: Wed, 01 Jan 2021 14:53:01 GMT.
static int registrar_validate_contacts(const pjsip_rx_data *rdata, pj_pool_t *pool, struct ao2_container *contacts, struct ast_sip_aor *aor, int permanent, int *added, int *updated, int *deleted)
Internal function which validates provided Contact headers to confirm that they are acceptable...
unsigned int ast_sip_get_contact_expiration_check_interval(void)
Retrieve the system contact expiration check interval setting.
int ast_sip_will_uri_survive_restart(pjsip_sip_uri *uri, struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
static int pj_max_hostname
Module has failed to load, may be in an inconsistent state.
An API for managing task processing threads that can be shared across modules.
static void * check_expiration_thread(void *data)
void(* loaded)(const char *object_type)
Callback for when an object type is loaded/reloaded.
int ast_sip_format_contact_ami(void *obj, void *arg, int flags)
Formats the contact and sends over AMI.
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.
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
static pjsip_module registrar_module
static int sip_contact_to_str(void *acp, void *arg, int flags)
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
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.
char * strsep(char **str, const char *delims)
static int registrar_contact_delete(enum contact_delete_type type, pjsip_transport *transport, struct ast_sip_contact *contact, const char *aor_name)
const ast_string_field domain
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
void * ast_sorcery_copy(const struct ast_sorcery *sorcery, const void *object)
Create a copy of an object.
void ast_sip_unregister_service(pjsip_module *module)
int ast_sip_sorcery_object_to_ami(const void *obj, struct ast_str **buf)
Converts a sorcery object to a string of object properties.
struct ao2_container * ast_sip_get_endpoints(void)
Retrieve any endpoints available to sorcery.
static const pj_str_t path_hdr_name
int ast_sip_location_update_contact(struct ast_sip_contact *contact)
Update a contact.
int ast_sip_for_each_contact(const struct ast_sip_aor *aor, ao2_callback_fn on_contact, void *arg)
For every contact on an AOR call the given 'on_contact' handler.
const ast_string_field aors
#define AMI_SHOW_REGISTRATION_CONTACT_STATUSES
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
#define ASTERISK_GPL_KEY
The text the key() function should return.
static unsigned int check_interval
The global interval at which to check for contact expiration.
Asterisk module definitions.
struct ast_sip_contact * ast_sip_location_retrieve_contact(const char *contact_name)
Retrieve a named contact.
unsigned int minimum_expiration
unsigned int default_expiration
unsigned int maximum_expiration
static int expire_contact(void *obj, void *arg, int flags)
Callback function which deletes a contact.
void ast_sip_transport_monitor_unregister_all(ast_transport_monitor_shutdown_cb cb, void *data, ast_transport_monitor_data_matcher matches)
Unregister a transport shutdown monitor from all reliable transports.
static struct ast_sorcery_observer expiration_global_observer
Observer which is used to update our interval when the global setting changes.
#define PJSIP_EXPIRES_NOT_SPECIFIED
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
static int registrar_add_contact(void *obj, void *arg, int flags)
Internal function which adds a contact to a response.
void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type)
Inform any wizards of a specific object type to reload persistent objects.
#define ast_named_lock_get(lock_type, keyspace, key)
Geta named lock handle.
unsigned int ast_sip_get_ignore_uri_user_options(void)
Retrieve the global setting 'ignore_uri_user_options'.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
#define ast_named_lock_put(lock)
Put a named lock handle away.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
#define AST_VECTOR_MAX_SIZE(vec)
Get the maximum number of elements the vector can currently hold.
#define ao2_link(container, obj)