Asterisk - The Open Source Telephony Project  GIT-master-e8cda4b
pjsip_options.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2018, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@digium.com>
7  * Richard Mudgett <rmudgett@digium.com>
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19 
20 #include "asterisk.h"
21 
22 #include <pjsip.h>
23 #include <pjsip_ua.h>
24 #include <pjlib.h>
25 
26 #include "asterisk/res_pjsip.h"
27 #include "asterisk/channel.h"
28 #include "asterisk/pbx.h"
29 #include "asterisk/astobj2.h"
30 #include "asterisk/cli.h"
31 #include "asterisk/time.h"
32 #include "asterisk/test.h"
33 #include "asterisk/statsd.h"
35 #include "asterisk/taskprocessor.h"
36 #include "asterisk/threadpool.h"
37 
38 /*
39  * This implementation for OPTIONS support is based around the idea
40  * that realistically an AOR generally has very few contacts and is
41  * referenced by only a few endpoints. While it is perfectly fine for
42  * use in opposite scenarios it works best in the above case. It is
43  * also not shy to keeping state but it is reactive to outside changes
44  * so it can be updated.
45  *
46  * The lowest level object in here is a contact and its associated
47  * contact status. The result of an OPTIONS request to a contact is
48  * reflected in the contact status. The scheduling of these OPTIONS
49  * request is driven by the AOR. The AOR periodicially (according to
50  * configuration) sends OPTIONS requests out to any contacts
51  * associated with it. Contacts themselves are not individually
52  * scheduled. Contacts can be added or deleted as appropriate with no
53  * requirement to reschedule.
54  *
55  * The next level object up is the AOR itself. The result of a contact
56  * status change is fed into it and the result composited with all
57  * other contacts. This may result in the AOR itself changing state
58  * (it can be either AVAILABLE or UNAVAILABLE).
59  *
60  * The highest level object up is the endpoint state compositor (ESC).
61  * The result of AOR state changes is fed into it and the result
62  * composited with all other referenced AORs. This may result in the
63  * endpoint itself changing state (it can be either ONLINE or
64  * OFFLINE). If this occurs the permanent endpoint is updated to
65  * reflect it.
66  *
67  * The threading model errs on the side of a world where things are
68  * not constantly changing. That is: A world where AORs and endpoints
69  * are not being constantly added/removed. This more closely mirrors
70  * the usage of the vast majority of people. This scenario can still
71  * be done but it may not be applied immediately.
72  *
73  * Manipulation of which AORs, endpoint state compositors, and
74  * contacts exist is done within a single serializer. This ensures
75  * that no matter the source threads order is preserved and you won't
76  * get into a weird situation where things are referencing other
77  * things that should have already been destroyed.
78  *
79  * Operations which impact the state of an AOR are done within a
80  * serializer that is specific to the AOR. This includes the result of
81  * a contact status change. This change is queued and executed on the
82  * AOR serializer afterwards.
83  *
84  * Operations which impact an endpoint state compositor are protected
85  * by a lock. This is done as the endpoint state compositor usage is
86  * minimal and the overhead of using a serializer and queueing things
87  * is not warranted.
88  *
89  * AORs which do not have a qualify frequency are also kept in here
90  * but do not require the same criteria as qualified AORs to be
91  * considered available. In their case as long as at least 1 contact
92  * is configured on the AOR (or added to it by registration) it is
93  * considered available.
94  */
95 
96 #define DEFAULT_LANGUAGE "en"
97 #define DEFAULT_ENCODING "identity"
98 
99 /*! \brief These are the number of buckets to store AORs in */
100 #ifdef LOW_MEMORY
101 #define AOR_BUCKETS 61
102 #else
103 #define AOR_BUCKETS 1567
104 #endif
105 
106 /*! \brief These are the number of contact status buckets */
107 #ifdef LOW_MEMORY
108 #define CONTACT_STATUS_BUCKETS 61
109 #else
110 #define CONTACT_STATUS_BUCKETS 1567
111 #endif
112 
113 /*! \brief These are the number of buckets (per AOR) to use to store contacts */
114 #define CONTACT_BUCKETS 13
115 
116 /*! \brief These are the number of buckets to store endpoint state compositors */
117 #define ENDPOINT_STATE_COMPOSITOR_BUCKETS 13
118 
119 /*! \brief The initial vector size for the endpoint state compositors on an AOR */
120 #define ENDPOINT_STATE_COMPOSITOR_INITIAL_SIZE 1
121 
122 /*! \brief These are the number of buckets (per endpoint state compositor) to use to store AOR statuses */
123 #define AOR_STATUS_BUCKETS 3
124 
125 /*! \brief Maximum wait time to join the below shutdown group */
126 #define MAX_UNLOAD_TIMEOUT_TIME 10 /* Seconds */
127 
128 /*! \brief Shutdown group for options serializers */
130 
131 /*!
132  * \brief Structure which contains status information for an AOR feeding an endpoint state compositor
133  */
135  /*! \brief The last contributed available status of the named AOR (1 if available, 0 if not available) */
136  char available;
137  /*! \brief The name of the AOR */
138  char name[0];
139 };
140 
141 /*!
142  * \brief Structure which contains composites information for endpoint state
143  */
145  /*! \brief The last contributed available status of the AORs feeding this compositor */
147  /*!
148  * \brief Non-zero if the compositor is in normal operation. i.e. Not being setup/reconfigured.
149  *
150  * \details
151  * The aor layer can only update its aor_statuses record when not active.
152  * When active the aor layer can update its aor_statuses record, calculate the new
153  * number of available aors, determine if the endpoint compositor changed state,
154  * and report it.
155  */
156  char active;
157  /*! \brief The name of the endpoint */
158  char name[0];
159 };
160 
161 /*!
162  * \brief Structure which contains an AOR and contacts for qualifying purposes
163  */
165  /*! \brief The scheduler task for this AOR */
167  /*! \brief The serializer for this AOR */
169  /*! \brief All contacts associated with this AOR */
171  /*!
172  * \brief Only dynamic contacts associated with this AOR
173  * \note Used to speed up applying AOR configuration by
174  * minimizing wild card sorcery access.
175  */
177  /*! \brief The endpoint state compositors we are feeding, a reference is held to each */
178  AST_VECTOR(, struct sip_options_endpoint_state_compositor *) compositors;
179  /*! \brief The number of available contacts on this AOR */
180  unsigned int available;
181  /*! \brief Frequency to send OPTIONS requests to AOR contacts. 0 is disabled. */
182  unsigned int qualify_frequency;
183  /*! If true authenticate the qualify challenge response if needed */
184  int authenticate_qualify;
185  /*! \brief Qualify timeout. 0 is diabled. */
186  double qualify_timeout;
187  /*! \brief The name of the AOR */
188  char name[0];
189 };
190 
191 /*!
192  * \internal
193  * \brief Container of active SIP AORs for qualifying
194  */
196 
197 /*!
198  * \internal
199  * \brief Container of contact statuses
200  */
202 
203 /*!
204  * \internal
205  * \brief Container of endpoint state compositors
206  */
208 
209 /*!
210  * \internal
211  * \brief Serializer for AOR, endpoint state compositor, and contact existence management
212  */
214 
215 static pj_status_t send_options_response(pjsip_rx_data *rdata, int code)
216 {
217  pjsip_endpoint *endpt = ast_sip_get_pjsip_endpoint();
218  pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
219  pjsip_transaction *trans = pjsip_rdata_get_tsx(rdata);
220  pjsip_tx_data *tdata;
221  const pjsip_hdr *hdr;
222  pj_status_t status;
223 
224  /* Make the response object */
225  status = ast_sip_create_response(rdata, code, NULL, &tdata);
226  if (status != PJ_SUCCESS) {
227  ast_log(LOG_ERROR, "Unable to create response (%d)\n", status);
228  return status;
229  }
230 
231  /* Add appropriate headers */
232  if ((hdr = pjsip_endpt_get_capability(endpt, PJSIP_H_ACCEPT, NULL))) {
233  pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)pjsip_hdr_clone(tdata->pool, hdr));
234  }
235  if ((hdr = pjsip_endpt_get_capability(endpt, PJSIP_H_ALLOW, NULL))) {
236  pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)pjsip_hdr_clone(tdata->pool, hdr));
237  }
238  if ((hdr = pjsip_endpt_get_capability(endpt, PJSIP_H_SUPPORTED, NULL))) {
239  pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)pjsip_hdr_clone(tdata->pool, hdr));
240  }
241 
242  /*
243  * XXX TODO: pjsip doesn't care a lot about either of these headers -
244  * while it provides specific methods to create them, they are defined
245  * to be the standard string header creation. We never did add them
246  * in chan_sip, although RFC 3261 says they SHOULD. Hard coded here.
247  */
248  ast_sip_add_header(tdata, "Accept-Encoding", DEFAULT_ENCODING);
249  ast_sip_add_header(tdata, "Accept-Language", DEFAULT_LANGUAGE);
250 
251  if (dlg && trans) {
252  status = pjsip_dlg_send_response(dlg, trans, tdata);
253  } else {
254  struct ast_sip_endpoint *endpoint;
255 
256  endpoint = ast_pjsip_rdata_get_endpoint(rdata);
257  status = ast_sip_send_stateful_response(rdata, tdata, endpoint);
258  ao2_cleanup(endpoint);
259  }
260 
261  if (status != PJ_SUCCESS) {
262  ast_log(LOG_ERROR, "Unable to send response (%d)\n", status);
263  }
264 
265  return status;
266 }
267 
268 static pj_bool_t options_on_rx_request(pjsip_rx_data *rdata)
269 {
270  RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
271  pjsip_uri *ruri;
272  pjsip_sip_uri *sip_ruri;
273  char exten[AST_MAX_EXTENSION];
274 
275  if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_options_method)) {
276  return PJ_FALSE;
277  }
278 
279  if (!(endpoint = ast_pjsip_rdata_get_endpoint(rdata))) {
280  return PJ_FALSE;
281  }
282 
283  ruri = rdata->msg_info.msg->line.req.uri;
284  if (!PJSIP_URI_SCHEME_IS_SIP(ruri) && !PJSIP_URI_SCHEME_IS_SIPS(ruri)) {
285  send_options_response(rdata, 416);
286  return PJ_TRUE;
287  }
288 
289  sip_ruri = pjsip_uri_get_uri(ruri);
290  ast_copy_pj_str(exten, &sip_ruri->user, sizeof(exten));
291 
292  /*
293  * We may want to match in the dialplan without any user
294  * options getting in the way.
295  */
297 
298  if (ast_shutting_down()) {
299  /*
300  * Not taking any new calls at this time.
301  * Likely a server availability OPTIONS poll.
302  */
303  send_options_response(rdata, 503);
304  } else if (!ast_strlen_zero(exten)
305  && !ast_exists_extension(NULL, endpoint->context, exten, 1, NULL)) {
306  send_options_response(rdata, 404);
307  } else {
308  send_options_response(rdata, 200);
309  }
310  return PJ_TRUE;
311 }
312 
313 static pjsip_module options_module = {
314  .name = {"Options Module", 14},
315  .id = -1,
316  .priority = PJSIP_MOD_PRIORITY_APPLICATION,
317  .on_rx_request = options_on_rx_request,
318 };
319 
320 static const char *status_map[] = {
321  [UNAVAILABLE] = "Unreachable",
322  [AVAILABLE] = "Reachable",
323  [UNKNOWN] = "Unknown",
324  [CREATED] = "NonQualified",
325  [REMOVED] = "Removed",
326 };
327 
328 static const char *short_status_map[] = {
329  [UNAVAILABLE] = "Unavail",
330  [AVAILABLE] = "Avail",
331  [UNKNOWN] = "Unknown",
332  [CREATED] = "NonQual",
333  [REMOVED] = "Removed",
334 };
335 
337 {
338  ast_assert(0 <= status && status < ARRAY_LEN(status_map));
339  return status_map[status];
340 }
341 
343 {
344  ast_assert(0 <= status && status < ARRAY_LEN(short_status_map));
345  return short_status_map[status];
346 }
347 
348 /*! \brief Destructor for contact statuses */
349 static void sip_contact_status_dtor(void *obj)
350 {
351  struct ast_sip_contact_status *contact_status = obj;
352 
353  ast_string_field_free_memory(contact_status);
354 }
355 
357 {
358  struct ast_sip_contact_status *contact_status;
359  size_t size = sizeof(*contact_status) + strlen(name) + 1;
360 
361  contact_status = ao2_alloc_options(size, sip_contact_status_dtor,
363  if (!contact_status) {
364  return NULL;
365  }
366  if (ast_string_field_init(contact_status, 256)) {
367  ao2_ref(contact_status, -1);
368  return NULL;
369  }
370  strcpy(contact_status->name, name); /* SAFE */
371  return contact_status;
372 }
373 
375 {
376  struct ast_sip_contact_status *dst;
377 
378  dst = sip_contact_status_alloc(src->name);
379  if (!dst) {
380  return NULL;
381  }
382 
383  if (ast_string_fields_copy(dst, src)) {
384  ao2_ref(dst, -1);
385  return NULL;
386  }
387  dst->rtt = src->rtt;
388  dst->status = src->status;
389  dst->last_status = src->last_status;
390  return dst;
391 }
392 
393 /*! \brief Hashing function for contact statuses */
395 
396 /*! \brief Sort function for contact statuses */
398 
399 /*! \brief Comparator function for contact statuses */
401 
402 /*! \brief Helper function to allocate a contact statuses container */
404 {
405  /*
406  * Replace duplicate objects so we can update the immutable
407  * contact status objects by simply linking in a new object.
408  */
411  ast_sip_contact_status_hash_fn, ast_sip_contact_status_sort_fn,
412  ast_sip_contact_status_cmp_fn);
413 }
414 
415 /*! \brief Function which publishes a contact status update to all interested endpoints */
416 static void sip_options_publish_contact_state(const struct sip_options_aor *aor_options,
417  const struct ast_sip_contact_status *contact_status)
418 {
419  int i;
420 
421  for (i = 0; i < AST_VECTOR_SIZE(&aor_options->compositors); ++i) {
422  const struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
423 
424  endpoint_state_compositor = AST_VECTOR_GET(&aor_options->compositors, i);
425  ast_sip_persistent_endpoint_publish_contact_state(endpoint_state_compositor->name,
426  contact_status);
427  }
428 }
429 
430 /*!
431  * \brief Task to notify endpoints of a contact status change
432  * \note Run by management_serializer
433  */
435 {
436  struct ast_sip_contact_status *contact_status = obj;
437  struct sip_options_aor *aor_options;
438 
439  aor_options = ao2_find(sip_options_aors, contact_status->aor, OBJ_SEARCH_KEY);
440  if (aor_options) {
441  sip_options_publish_contact_state(aor_options, contact_status);
442  ao2_ref(aor_options, -1);
443  }
444  ao2_ref(contact_status, -1);
445 
446  return 0;
447 }
448 
450 {
451  struct ast_taskprocessor *mgmt_serializer = management_serializer;
452 
453  if (mgmt_serializer) {
454  ao2_ref(contact_status, +1);
456  contact_status)) {
457  ao2_ref(contact_status, -1);
458  }
459  }
460 }
461 
463 {
464  struct ast_sip_contact_status *contact_status;
465  int res;
466 
467  /*
468  * At startup a contact status can be retrieved when static contacts
469  * are themselves being setup. This happens before we are fully setup.
470  * Since we don't actually trigger qualify or anything as a result it
471  * is safe to do so. They'll just get back a contact status that will
472  * be updated later. At this time they only care that the contact
473  * status gets created for the static contact anyway.
474  */
475  if (!sip_options_contact_statuses) {
476  /*
477  * We haven't been pre-initialized or we are shutting down.
478  * Neither situation should happen.
479  */
480  ast_assert(0);
481  return NULL;
482  }
483 
484  ao2_lock(sip_options_contact_statuses);
485 
486  /* If contact status for this contact already exists just return it */
487  contact_status = ao2_find(sip_options_contact_statuses,
489  if (contact_status) {
490  ao2_unlock(sip_options_contact_statuses);
491  return contact_status;
492  }
493 
494  /* Otherwise we have to create and store a new contact status */
495  contact_status = sip_contact_status_alloc(ast_sorcery_object_get_id(contact));
496  if (!contact_status) {
497  ao2_unlock(sip_options_contact_statuses);
498  return NULL;
499  }
500 
501  contact_status->rtt = 0;
502  contact_status->status = CREATED;
503  contact_status->last_status = CREATED;
504  res = ast_string_field_set(contact_status, uri, contact->uri);
505  res |= ast_string_field_set(contact_status, aor, contact->aor);
506  if (res) {
507  ao2_unlock(sip_options_contact_statuses);
508  ao2_ref(contact_status, -1);
509  return NULL;
510  }
511 
512  ao2_link_flags(sip_options_contact_statuses, contact_status, OBJ_NOLOCK);
513  ao2_unlock(sip_options_contact_statuses);
514 
515  ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
516  "+1", 1.0, ast_sip_get_contact_status_label(contact_status->status));
517 
518  sip_options_contact_status_update(contact_status);
519 
520  return contact_status;
521 }
522 
524 {
525  return ao2_find(sip_options_contact_statuses, ast_sorcery_object_get_id(contact),
527 }
528 
529 /*! \brief Hashing function for OPTIONS AORs */
531 
532 /*! \brief Comparator function for SIP OPTIONS AORs */
534 
535 /*! \brief Hashing function for endpoint state compositors */
537 
538 /*! \brief Comparator function for endpoint state compositors */
540 
541 /*! \brief Structure used to contain information for an OPTIONS callback */
543  /*! \brief The contact we qualified */
545  /*! \brief The AOR options */
547  /*! \brief The time at which this OPTIONS attempt was started */
548  struct timeval rtt_start;
549  /*! \brief The new status of the contact */
551 };
552 
553 /*!
554  * \brief Return the current state of an endpoint state compositor
555  * \pre The endpoint_state_compositor lock must be held.
556  */
558  const struct sip_options_endpoint_state_compositor *endpoint_state_compositor)
559 {
560  struct ao2_iterator it_aor_statuses;
561  struct sip_options_endpoint_aor_status *aor_status;
563 
564  it_aor_statuses = ao2_iterator_init(endpoint_state_compositor->aor_statuses, 0);
565  for (; (aor_status = ao2_iterator_next(&it_aor_statuses)); ao2_ref(aor_status, -1)) {
566  if (aor_status->available) {
567  state = AST_ENDPOINT_ONLINE;
568  ao2_ref(aor_status, -1);
569  break;
570  }
571  }
572  ao2_iterator_destroy(&it_aor_statuses);
573 
574  return state;
575 }
576 
577 /*!
578  * \brief Update the AOR status on an endpoint state compositor
579  * \pre The endpoint_state_compositor lock must be held.
580  */
582  const char *name, enum ast_sip_contact_status_type status)
583 {
584  struct sip_options_endpoint_aor_status *aor_status;
585  enum ast_endpoint_state endpoint_state;
586 
587  aor_status = ao2_find(endpoint_state_compositor->aor_statuses, name,
589  if (!aor_status) {
590  /* The AOR status doesn't exist already so we don't need to go any further */
591  if (status == REMOVED) {
592  return;
593  }
594 
595  aor_status = ao2_alloc_options(sizeof(*aor_status) + strlen(name) + 1, NULL,
597  if (!aor_status) {
598  return;
599  }
600 
601  strcpy(aor_status->name, name); /* SAFE */
602  ao2_link(endpoint_state_compositor->aor_statuses, aor_status);
603  }
604 
605  if (status == REMOVED) {
606  /*
607  * If the AOR is being removed then remove its AOR status
608  * from the endpoint compositor.
609  */
610  ao2_unlink(endpoint_state_compositor->aor_statuses, aor_status);
611  } else {
612  aor_status->available = (status == AVAILABLE ? 1 : 0);
613  }
614  ao2_ref(aor_status, -1);
615 
616  if (!endpoint_state_compositor->active) {
617  return;
618  }
619 
620  /* If this AOR is available then the endpoint itself has to be online */
621  if (status == AVAILABLE) {
622  ast_debug(3, "Endpoint state compositor '%s' is online as AOR '%s' is available\n",
623  endpoint_state_compositor->name, name);
624  endpoint_state = AST_ENDPOINT_ONLINE;
625  } else {
626  endpoint_state =
627  sip_options_get_endpoint_state_compositor_state(endpoint_state_compositor);
628  }
629 
630  ast_sip_persistent_endpoint_update_state(endpoint_state_compositor->name,
631  endpoint_state);
632 }
633 
634 /*! \brief Function which notifies endpoint state compositors of a state change of an AOR */
637 {
638  int i;
639 
640  /* Iterate through the associated endpoint state compositors updating them */
641  for (i = 0; i < AST_VECTOR_SIZE(&aor_options->compositors); ++i) {
642  struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
643 
644  endpoint_state_compositor = AST_VECTOR_GET(&aor_options->compositors, i);
645 
646  ao2_lock(endpoint_state_compositor);
647  sip_options_update_endpoint_state_compositor_aor(endpoint_state_compositor,
648  aor_options->name, status);
649  ao2_unlock(endpoint_state_compositor);
650  }
651 
652  if (status == REMOVED) {
653  AST_VECTOR_RESET(&aor_options->compositors, ao2_cleanup);
654  }
655 }
656 
657 /*!
658  * \brief Task to notify an AOR of a contact status change
659  * \note Run by aor_options->serializer
660  */
662 {
663  struct sip_options_contact_callback_data *contact_callback_data = obj;
664  struct ast_sip_contact *contact;
665  struct ast_sip_contact_status *cs_old;
666  struct ast_sip_contact_status *cs_new;
667 
668  /*
669  * Determine if this is a late arriving notification, as it is
670  * possible that we get a callback from PJSIP giving us contact
671  * status but in the mean time said contact has been removed
672  * from the controlling AOR.
673  */
674 
675  if (!contact_callback_data->aor_options->qualify_frequency) {
676  /* Contact qualify response is late */
677  ao2_ref(contact_callback_data, -1);
678  return 0;
679  }
680 
681  contact = ao2_find(contact_callback_data->aor_options->contacts,
682  contact_callback_data->contact, OBJ_SEARCH_OBJECT);
683  if (!contact) {
684  /* Contact qualify response is late */
685  ao2_ref(contact_callback_data, -1);
686  return 0;
687  }
688  ao2_ref(contact, -1);
689 
690  cs_old = ao2_find(sip_options_contact_statuses,
691  ast_sorcery_object_get_id(contact_callback_data->contact), OBJ_SEARCH_KEY);
692  if (!cs_old) {
693  /* Contact qualify response is late */
694  ao2_ref(contact_callback_data, -1);
695  return 0;
696  }
697 
698  /* Update the contact specific status information */
699  cs_new = sip_contact_status_copy(cs_old);
700  ao2_ref(cs_old, -1);
701  if (!cs_new) {
702  ao2_ref(contact_callback_data, -1);
703  return 0;
704  }
705  cs_new->last_status = cs_new->status;
706  cs_new->status = contact_callback_data->status;
707  cs_new->rtt =
708  cs_new->status == AVAILABLE
709  ? ast_tvdiff_us(ast_tvnow(), contact_callback_data->rtt_start)
710  : 0;
711  ao2_link(sip_options_contact_statuses, cs_new);
712 
713  /*
714  * If the status has changed then notify the endpoint state compositors
715  * and publish our events.
716  */
717  if (cs_new->last_status != cs_new->status) {
718  if (cs_new->status == AVAILABLE) {
719  /* If this is the first available contact then the AOR has become available */
720  ++contact_callback_data->aor_options->available;
721  if (contact_callback_data->aor_options->available == 1) {
723  contact_callback_data->aor_options, AVAILABLE);
724  }
725  } else if (cs_new->last_status == AVAILABLE) {
726  ast_assert(cs_new->status == UNAVAILABLE);
727 
728  /* If there are no more available contacts then this AOR is unavailable */
729  --contact_callback_data->aor_options->available;
730  if (!contact_callback_data->aor_options->available) {
732  contact_callback_data->aor_options, UNAVAILABLE);
733  }
734  }
735 
736  ast_verb(3, "Contact %s/%s is now %s. RTT: %.3f msec\n",
737  cs_new->aor,
738  cs_new->uri,
740  cs_new->rtt / 1000.0);
741 
742  ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
743  "-1", 1.0, ast_sip_get_contact_status_label(cs_new->last_status));
744  ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
745  "+1", 1.0, ast_sip_get_contact_status_label(cs_new->status));
746 
748 
749  ast_test_suite_event_notify("AOR_CONTACT_UPDATE",
750  "Contact: %s\r\n"
751  "Status: %s",
752  cs_new->name,
754  } else {
755  ast_debug(3, "Contact %s/%s status didn't change: %s, RTT: %.3f msec\n",
756  cs_new->aor,
757  cs_new->uri,
759  cs_new->rtt / 1000.0);
760  }
761 
762  ast_statsd_log_full_va("PJSIP.contacts.%s.rtt", AST_STATSD_TIMER,
763  cs_new->status != AVAILABLE ? -1 : cs_new->rtt / 1000,
764  1.0,
765  cs_new->name);
766 
767  ast_test_suite_event_notify("AOR_CONTACT_QUALIFY_RESULT",
768  "Contact: %s\r\n"
769  "Status: %s\r\n"
770  "RTT: %" PRId64,
771  cs_new->name,
773  cs_new->rtt);
774 
775  ast_debug(3, "AOR '%s' now has %d available contacts\n",
776  contact_callback_data->aor_options->name,
777  contact_callback_data->aor_options->available);
778 
779  ao2_ref(cs_new, -1);
780  ao2_ref(contact_callback_data, -1);
781 
782  return 0;
783 }
784 
785 /*! \brief Callback for when we get a result from a SIP OPTIONS request (a response or a timeout) */
786 static void qualify_contact_cb(void *token, pjsip_event *e)
787 {
788  struct sip_options_contact_callback_data *contact_callback_data = token;
790 
791  switch(e->body.tsx_state.type) {
792  default:
793  ast_log(LOG_ERROR, "Unexpected PJSIP event %u\n", e->body.tsx_state.type);
794  /* Fall through */
795  case PJSIP_EVENT_TRANSPORT_ERROR:
796  case PJSIP_EVENT_TIMER:
797  status = UNAVAILABLE;
798  break;
799  case PJSIP_EVENT_RX_MSG:
800  status = AVAILABLE;
801  break;
802  }
803 
804  /* Update the callback data with the new status, this will get handled in the AOR serializer */
805  contact_callback_data->status = status;
806 
807  if (ast_sip_push_task(contact_callback_data->aor_options->serializer,
808  sip_options_contact_status_notify_task, contact_callback_data)) {
809  ast_log(LOG_NOTICE, "Unable to queue contact status update for '%s' on AOR '%s', state will be incorrect\n",
810  ast_sorcery_object_get_id(contact_callback_data->contact),
811  contact_callback_data->aor_options->name);
812  ao2_ref(contact_callback_data, -1);
813  }
814 
815  /* The task inherited our reference so we don't unreference here */
816 }
817 
818 /*! \brief Destructor for contact callback data */
820 {
821  struct sip_options_contact_callback_data *contact_callback_data = obj;
822 
823  ao2_cleanup(contact_callback_data->contact);
824  ao2_cleanup(contact_callback_data->aor_options);
825 }
826 
827 /*! \brief Contact callback data allocator */
830 {
831  struct sip_options_contact_callback_data *contact_callback_data;
832 
833  contact_callback_data = ao2_alloc_options(sizeof(*contact_callback_data),
835  if (!contact_callback_data) {
836  return NULL;
837  }
838 
839  contact_callback_data->contact = ao2_bump(contact);
840  contact_callback_data->aor_options = ao2_bump(aor_options);
841  contact_callback_data->rtt_start = ast_tvnow();
842 
843  return contact_callback_data;
844 }
845 
846 /*! \brief Send a SIP OPTIONS request for a contact */
847 static int sip_options_qualify_contact(void *obj, void *arg, int flags)
848 {
849  struct ast_sip_contact *contact = obj;
850  struct sip_options_aor *aor_options = arg;
851  RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
852  pjsip_tx_data *tdata;
853  struct ast_sip_contact_status *contact_status;
854  struct sip_options_contact_callback_data *contact_callback_data;
855 
856  ast_debug(3, "Qualifying contact '%s' on AOR '%s'\n",
857  ast_sorcery_object_get_id(contact), aor_options->name);
858 
859  if (!ast_strlen_zero(contact->endpoint_name)) {
860  endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
861  contact->endpoint_name);
862  }
863  if (!endpoint && AST_VECTOR_SIZE(&aor_options->compositors)) {
864  struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
865 
866  endpoint_state_compositor = AST_VECTOR_GET(&aor_options->compositors, 0);
867  endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
868  endpoint_state_compositor->name);
869  }
870  if (!endpoint) {
871  ast_debug(3, "Could not find an endpoint to qualify contact '%s' on AOR '%s'\n",
872  ast_sorcery_object_get_id(contact), aor_options->name);
873  return 0;
874  }
875 
876  if (ast_sip_create_request("OPTIONS", NULL, endpoint, NULL, contact, &tdata)) {
877  ast_log(LOG_ERROR, "Unable to create request to qualify contact %s on AOR %s\n",
878  contact->uri, aor_options->name);
879  return 0;
880  }
881 
882  /* If an outbound proxy is specified set it on this request */
883  if (!ast_strlen_zero(contact->outbound_proxy) &&
884  ast_sip_set_outbound_proxy(tdata, contact->outbound_proxy)) {
885  ast_log(LOG_ERROR, "Unable to apply outbound proxy on request to qualify contact %s\n",
886  contact->uri);
887  pjsip_tx_data_dec_ref(tdata);
888  return 0;
889  }
890 
891  contact_status = ast_res_pjsip_find_or_create_contact_status(contact);
892  if (!contact_status) {
893  ast_log(LOG_ERROR, "Unable to retrieve contact status information for contact %s on AOR %s\n",
894  contact->uri, aor_options->name);
895  pjsip_tx_data_dec_ref(tdata);
896  return 0;
897  }
898  ao2_ref(contact_status, -1);
899 
900  contact_callback_data = sip_options_contact_callback_data_alloc(contact, aor_options);
901  if (!contact_callback_data) {
902  ast_log(LOG_ERROR, "Unable to create object to contain callback data for contact %s on AOR %s\n",
903  contact->uri, aor_options->name);
904  pjsip_tx_data_dec_ref(tdata);
905  return 0;
906  }
907 
908  if (ast_sip_send_out_of_dialog_request(tdata, endpoint,
909  (int)(aor_options->qualify_timeout * 1000), contact_callback_data,
911  ast_log(LOG_ERROR, "Unable to send request to qualify contact %s on AOR %s\n",
912  contact->uri, aor_options->name);
913  ao2_ref(contact_callback_data, -1);
914  }
915 
916  return 0;
917 }
918 
919 /*!
920  * \brief Task to qualify contacts of an AOR
921  * \note Run by aor_options->serializer
922  */
923 static int sip_options_qualify_aor(void *obj)
924 {
925  struct sip_options_aor *aor_options = obj;
926 
927  ast_debug(3, "Qualifying all contacts on AOR '%s'\n", aor_options->name);
928 
929  /* Attempt to send an OPTIONS request to every contact on this AOR */
931  (struct sip_options_aor *) aor_options);
932 
933  /* Always reschedule to the frequency we should go */
934  return aor_options->qualify_frequency * 1000;
935 }
936 
937 /*! \brief Forward declaration of this helpful function */
938 static int sip_options_remove_contact(void *obj, void *arg, int flags);
939 
940 /*! \brief Destructor function for SIP OPTIONS AORs */
941 static void sip_options_aor_dtor(void *obj)
942 {
943  struct sip_options_aor *aor_options = obj;
944 
945  /*
946  * Any contacts are unreachable since the AOR is being destroyed
947  * so remove their contact status
948  */
949  if (aor_options->contacts) {
950  ao2_callback(aor_options->contacts, OBJ_NODATA | OBJ_UNLINK,
951  sip_options_remove_contact, aor_options);
952  ao2_ref(aor_options->contacts, -1);
953  }
954  ao2_cleanup(aor_options->dynamic_contacts);
955 
957 
958  ast_assert(AST_VECTOR_SIZE(&aor_options->compositors) == 0);
959  AST_VECTOR_FREE(&aor_options->compositors);
960 }
961 
962 /*! \brief Allocator for AOR OPTIONS */
964 {
965  struct sip_options_aor *aor_options;
966  char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];
967 
968  aor_options = ao2_alloc_options(sizeof(*aor_options) + strlen(ast_sorcery_object_get_id(aor)) + 1,
970  if (!aor_options) {
971  return NULL;
972  }
973 
974  strcpy(aor_options->name, ast_sorcery_object_get_id(aor)); /* SAFE */
975 
976  ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "pjsip/options/%s",
978  aor_options->serializer = ast_sip_create_serializer_group(tps_name,
979  shutdown_group);
980  if (!aor_options->serializer) {
981  ao2_ref(aor_options, -1);
982  return NULL;
983  }
984 
985  if (AST_VECTOR_INIT(&aor_options->compositors, ENDPOINT_STATE_COMPOSITOR_INITIAL_SIZE)) {
986  ao2_ref(aor_options, -1);
987  return NULL;
988  }
989 
993  if (!aor_options->contacts) {
994  ao2_ref(aor_options, -1);
995  return NULL;
996  }
997 
1001  if (!aor_options->dynamic_contacts) {
1002  ao2_ref(aor_options, -1);
1003  return NULL;
1004  }
1005 
1006  return aor_options;
1007 }
1008 
1009 /*! \brief Remove contact status for a hint */
1010 static void sip_options_remove_contact_status(struct sip_options_aor *aor_options,
1011  struct ast_sip_contact *contact)
1012 {
1013  struct ast_sip_contact_status *cs_new;
1014  struct ast_sip_contact_status *cs_old;
1015 
1016  cs_old = ao2_find(sip_options_contact_statuses, ast_sorcery_object_get_id(contact),
1018  if (!cs_old) {
1019  ast_debug(3, "Attempted to remove contact status for '%s' but it does not exist\n",
1020  ast_sorcery_object_get_id(contact));
1021  return;
1022  }
1023 
1024  ast_verb(2, "Contact %s/%s has been deleted\n", contact->aor, contact->uri);
1025 
1026  /* Update the contact status to reflect its new state */
1027  cs_new = sip_contact_status_copy(cs_old);
1028  if (!cs_new) {
1029  /*
1030  * We'll have to violate the immutable property because we
1031  * couldn't create a new one to modify and we are deleting
1032  * the contact status anyway.
1033  */
1034  cs_new = cs_old;
1035  } else {
1036  ao2_ref(cs_old, -1);
1037  }
1038  cs_new->last_status = cs_new->status;
1039  cs_new->status = REMOVED;
1040  cs_new->rtt = 0;
1041 
1042  ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
1043  "-1", 1.0, ast_sip_get_contact_status_label(cs_new->last_status));
1044  ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
1045  "+1", 1.0, ast_sip_get_contact_status_label(cs_new->status));
1046 
1048 
1049  /*
1050  * The only time we need to update the AOR is if this contact was
1051  * available and qualify is in use, otherwise we can just stop
1052  * early.
1053  */
1054  if (!aor_options->qualify_frequency || cs_new->last_status != AVAILABLE) {
1055  ao2_ref(cs_new, -1);
1056  return;
1057  }
1058 
1059  --aor_options->available;
1060  if (!aor_options->available) {
1062  }
1063 
1064  ast_debug(3, "AOR '%s' now has %d available contacts\n", aor_options->name,
1065  aor_options->available);
1066 
1067  ao2_ref(cs_new, -1);
1068 }
1069 
1070 /*! \brief Task data for AOR creation or updating */
1072  /*! \brief The AOR options for this AOR */
1074  /*! \brief The AOR which contains the new configuraton */
1075  struct ast_sip_aor *aor;
1076  /*! \brief Optional container of existing AOR s*/
1078  /*! \brief Whether this AOR is being added */
1079  int added;
1080 };
1081 
1082 /*! \brief Callback function to remove a contact and its contact status from an AOR */
1083 static int sip_options_remove_contact(void *obj, void *arg, int flags)
1084 {
1085  struct ast_sip_contact *contact = obj;
1086  struct sip_options_aor *aor_options = arg;
1087 
1088  sip_options_remove_contact_status(aor_options, contact);
1089 
1090  return CMP_MATCH;
1091 }
1092 
1093 /*! \brief Determine an initial time for scheduling AOR qualifying */
1094 static int sip_options_determine_initial_qualify_time(int qualify_frequency)
1095 {
1096  int initial_interval;
1097  int max_time = ast_sip_get_max_initial_qualify_time();
1098 
1099  if (max_time && max_time < qualify_frequency) {
1100  initial_interval = max_time;
1101  } else {
1102  initial_interval = qualify_frequency;
1103  }
1104 
1105  initial_interval = (int)((initial_interval * 1000) * ast_random_double());
1106  return 0 < initial_interval ? initial_interval : 1;
1107 }
1108 
1109 /*! \brief Set the contact status for a contact */
1110 static void sip_options_set_contact_status(struct ast_sip_contact_status *contact_status,
1112 {
1113  struct ast_sip_contact_status *cs_new;
1114 
1115  /* Update the contact specific status information */
1116  cs_new = sip_contact_status_copy(contact_status);
1117  if (!cs_new) {
1118  return;
1119  }
1120  cs_new->last_status = cs_new->status;
1121  cs_new->status = status;
1122 
1123  /*
1124  * We need to always set the RTT to zero because we haven't completed
1125  * an OPTIONS ping so RTT is unknown. If the OPTIONS ping were still
1126  * running it will be refreshed on the next go round anyway.
1127  */
1128  cs_new->rtt = 0;
1129 
1130  ao2_link(sip_options_contact_statuses, cs_new);
1131 
1132  if (cs_new->status != cs_new->last_status) {
1133  ast_verb(3, "Contact %s/%s is now %s.\n",
1134  cs_new->aor, cs_new->uri,
1136 
1137  ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
1138  "-1", 1.0, ast_sip_get_contact_status_label(cs_new->last_status));
1139  ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE,
1140  "+1", 1.0, ast_sip_get_contact_status_label(cs_new->status));
1141 
1143 
1144  ast_test_suite_event_notify("AOR_CONTACT_UPDATE",
1145  "Contact: %s\r\n"
1146  "Status: %s",
1147  cs_new->name,
1149  }
1150  ao2_ref(cs_new, -1);
1151 }
1152 
1153 /*! \brief Transition the contact status to unqualified mode */
1154 static int sip_options_set_contact_status_unqualified(void *obj, void *arg, int flags)
1155 {
1156  struct ast_sip_contact *contact = obj;
1157  struct ast_sip_contact_status *contact_status;
1158 
1159  contact_status = ast_res_pjsip_find_or_create_contact_status(contact);
1160  if (!contact_status) {
1161  return 0;
1162  }
1163 
1164  switch (contact_status->status) {
1165  case AVAILABLE:
1166  case UNAVAILABLE:
1167  case UNKNOWN:
1168  sip_options_set_contact_status(contact_status, CREATED);
1169  break;
1170  case CREATED:
1171  case REMOVED:
1172  break;
1173  }
1174 
1175  ao2_ref(contact_status, -1);
1176 
1177  return 0;
1178 }
1179 
1180 /*! \brief Transition the contact status to qualified mode */
1181 static int sip_options_set_contact_status_qualified(void *obj, void *arg, int flags)
1182 {
1183  struct ast_sip_contact *contact = obj;
1184  struct ast_sip_contact_status *contact_status;
1185 
1186  contact_status = ast_res_pjsip_find_or_create_contact_status(contact);
1187  if (!contact_status) {
1188  return 0;
1189  }
1190 
1191  switch (contact_status->status) {
1192  case AVAILABLE:
1194  break;
1195  case UNAVAILABLE:
1196  case UNKNOWN:
1197  case CREATED:
1198  case REMOVED:
1199  break;
1200  }
1201 
1202  ao2_ref(contact_status, -1);
1203 
1204  return 0;
1205 }
1206 
1207 /*! \brief Count AVAILABLE qualified contacts. */
1208 static int sip_options_contact_status_available_count(void *obj, void *arg, int flags)
1209 {
1210  struct ast_sip_contact *contact = obj;
1211  unsigned int *available = arg;
1212  struct ast_sip_contact_status *contact_status;
1213 
1214  contact_status = ast_res_pjsip_find_or_create_contact_status(contact);
1215  if (!contact_status) {
1216  return 0;
1217  }
1218 
1219  /* Count qualified available contacts. */
1220  switch (contact_status->status) {
1221  case AVAILABLE:
1222  ++*available;
1223  break;
1224  case UNAVAILABLE:
1225  case UNKNOWN:
1226  case CREATED:
1227  case REMOVED:
1228  break;
1229  }
1230 
1231  ao2_ref(contact_status, -1);
1232 
1233  return 0;
1234 }
1235 
1236 /*!
1237  * \brief Function which applies configuration to an AOR options structure
1238  * \note Run by aor_options->serializer (or management_serializer on aor_options creation)
1239  */
1241  struct ast_sip_aor *aor, int is_new)
1242 {
1243  struct ao2_container *existing_contacts;
1244  struct ast_sip_contact *contact;
1245  struct ao2_iterator iter;
1246 
1247  ast_debug(3, "Configuring AOR '%s' with current state of configuration and world\n",
1248  aor_options->name);
1249 
1250  /*
1251  * Permanent contacts, since we receive no notification that they
1252  * are gone, follow the same approach as AORs. We create a copy
1253  * of the existing container and any reused contacts are removed
1254  * from it. Any contacts remaining in the container after
1255  * processing no longer exist so we need to remove their state.
1256  */
1257  existing_contacts = ao2_container_clone(aor_options->contacts, 0);
1258  if (!existing_contacts) {
1259  ast_log(LOG_WARNING, "Synchronization of AOR '%s' failed for qualify, retaining existing state\n",
1260  aor_options->name);
1261  return;
1262  }
1263 
1265  NULL, NULL);
1266 
1267  /* Process permanent contacts */
1268  if (aor->permanent_contacts) {
1269  iter = ao2_iterator_init(aor->permanent_contacts, 0);
1270  for (; (contact = ao2_iterator_next(&iter)); ao2_ref(contact, -1)) {
1271  ao2_find(existing_contacts, ast_sorcery_object_get_id(contact),
1273  ao2_link(aor_options->contacts, contact);
1274  }
1275  ao2_iterator_destroy(&iter);
1276  }
1277 
1278  /*
1279  * If this is newly added we need to see if there are any
1280  * existing dynamic contacts to add. Ones that are added
1281  * after creation will occur as a result of the contact
1282  * observer creation callback.
1283  */
1284  if (is_new) {
1285  size_t prefix_len = strlen(ast_sorcery_object_get_id(aor)) + sizeof(";@") - 1;
1286  char prefix[prefix_len + 1];
1287  struct ao2_container *contacts;
1288 
1289  sprintf(prefix, "%s;@", ast_sorcery_object_get_id(aor)); /* Safe */
1290  contacts = ast_sorcery_retrieve_by_prefix(ast_sip_get_sorcery(), "contact",
1291  prefix, prefix_len);
1292  if (contacts) {
1293  ao2_container_dup(aor_options->dynamic_contacts, contacts, 0);
1294  ao2_ref(contacts, -1);
1295  }
1296  }
1297 
1298  /* Process dynamic contacts */
1299  iter = ao2_iterator_init(aor_options->dynamic_contacts, 0);
1300  for (; (contact = ao2_iterator_next(&iter)); ao2_ref(contact, -1)) {
1301  ao2_find(existing_contacts, ast_sorcery_object_get_id(contact),
1303  ao2_link(aor_options->contacts, contact);
1304  }
1305  ao2_iterator_destroy(&iter);
1306 
1307  /* Any contacts left no longer exist, so raise events and make them disappear */
1308  ao2_callback(existing_contacts, OBJ_NODATA | OBJ_UNLINK,
1309  sip_options_remove_contact, aor_options);
1310  ao2_ref(existing_contacts, -1);
1311 
1312  /*
1313  * Update the available count if we transition between qualified
1314  * and unqualified. In the qualified case we need to start with
1315  * 0 available as the qualify process will take care of it. In
1316  * the unqualified case it is based on the number of contacts
1317  * present.
1318  */
1319  if (!aor->qualify_frequency) {
1320  ao2_callback(aor_options->contacts, OBJ_NODATA,
1322  aor_options->available = ao2_container_count(aor_options->contacts);
1323  ast_debug(3, "AOR '%s' is unqualified, number of available contacts is therefore '%d'\n",
1324  aor_options->name, aor_options->available);
1325  } else if (!aor_options->qualify_frequency) {
1326  ao2_callback(aor_options->contacts, OBJ_NODATA,
1328  aor_options->available = 0;
1329  ast_debug(3, "AOR '%s' has transitioned from unqualified to qualified, reset available contacts to 0\n",
1330  aor_options->name);
1331  } else {
1332  /*
1333  * Count the number of AVAILABLE qualified contacts to ensure
1334  * the count is in sync with reality.
1335  */
1336  aor_options->available = 0;
1337  ao2_callback(aor_options->contacts, OBJ_NODATA,
1338  sip_options_contact_status_available_count, &aor_options->available);
1339  }
1340 
1341  aor_options->authenticate_qualify = aor->authenticate_qualify;
1342  aor_options->qualify_timeout = aor->qualify_timeout;
1343 
1344  /*
1345  * If we need to stop or start the scheduled callback then do so.
1346  * This occurs due to the following:
1347  * 1. The qualify frequency has changed
1348  * 2. Contacts were added when previously there were none
1349  * 3. There are no contacts but previously there were some
1350  */
1351  if (aor_options->qualify_frequency != aor->qualify_frequency
1352  || (!aor_options->sched_task && ao2_container_count(aor_options->contacts))
1353  || (aor_options->sched_task && !ao2_container_count(aor_options->contacts))) {
1354  if (aor_options->sched_task) {
1355  ast_sip_sched_task_cancel(aor_options->sched_task);
1356  ao2_ref(aor_options->sched_task, -1);
1357  aor_options->sched_task = NULL;
1358  }
1359 
1360  /* If there is still a qualify frequency then schedule this */
1361  aor_options->qualify_frequency = aor->qualify_frequency;
1362  if (aor_options->qualify_frequency
1363  && ao2_container_count(aor_options->contacts)) {
1364  aor_options->sched_task = ast_sip_schedule_task(aor_options->serializer,
1365  sip_options_determine_initial_qualify_time(aor_options->qualify_frequency),
1368  if (!aor_options->sched_task) {
1369  ast_log(LOG_ERROR, "Unable to schedule qualify for contacts of AOR '%s'\n",
1370  aor_options->name);
1371  }
1372  }
1373  }
1374 
1375  ast_debug(3, "AOR '%s' now has %d available contacts\n", aor_options->name,
1376  aor_options->available);
1377 }
1378 
1379 /*!
1380  * \brief Task to synchronize an AOR with our local state
1381  * \note Run by aor_options->serializer (or management_serializer on aor_options creation)
1382  */
1384 {
1386  int i;
1387 
1388  ast_debug(3, "Synchronizing AOR '%s' with current state of configuration and world\n",
1389  task_data->aor_options->name);
1390 
1391  sip_options_apply_aor_configuration(task_data->aor_options, task_data->aor,
1392  task_data->added);
1393 
1394  /*
1395  * Endpoint state compositors are removed in this operation but not
1396  * added. To reduce the amount of work done they are done later. In
1397  * the mean time things can still qualify and once an endpoint state
1398  * compositor is added to the AOR it will be updated with the current
1399  * state.
1400  */
1401  for (i = 0; i < AST_VECTOR_SIZE(&task_data->aor_options->compositors); ++i) {
1402  struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1403 
1404  endpoint_state_compositor = AST_VECTOR_GET(&task_data->aor_options->compositors, i);
1405 
1406  ao2_lock(endpoint_state_compositor);
1407  endpoint_state_compositor->active = 0;
1408  sip_options_update_endpoint_state_compositor_aor(endpoint_state_compositor,
1409  task_data->aor_options->name, REMOVED);
1410  ao2_unlock(endpoint_state_compositor);
1411  }
1412  AST_VECTOR_RESET(&task_data->aor_options->compositors, ao2_cleanup);
1413 
1414  return 0;
1415 }
1416 
1417 /*!
1418  * \brief Synchronize an AOR with our local state
1419  * \note Run by management_serializer
1420  */
1421 static int sip_options_synchronize_aor(void *obj, void *arg, int flags)
1422 {
1423  struct sip_options_synchronize_aor_task_data task_data = {
1424  .aor = obj,
1425  .existing = arg,
1426  };
1427 
1428  task_data.aor_options = ao2_find(sip_options_aors,
1430  if (!task_data.aor_options) {
1431  task_data.aor_options = sip_options_aor_alloc(task_data.aor);
1432  if (!task_data.aor_options) {
1433  return 0;
1434  }
1435 
1436  task_data.added = 1;
1437 
1438  /* Nothing is aware of this AOR yet so we can just update it in this thread */
1440  ao2_link(sip_options_aors, task_data.aor_options);
1441  } else {
1442  /* This AOR already exists so we have to do manipulation in its serializer */
1444  sip_options_synchronize_aor_task, &task_data);
1445  }
1446 
1447  ao2_ref(task_data.aor_options, -1);
1448 
1449  if (task_data.existing) {
1450  ao2_find(task_data.existing, ast_sorcery_object_get_id(task_data.aor),
1452  }
1453 
1454  return 0;
1455 }
1456 
1457 /*! \brief Destructor for endpoint state compositors */
1459 {
1460  struct sip_options_endpoint_state_compositor *endpoint_state_compositor = obj;
1461 
1462  ao2_cleanup(endpoint_state_compositor->aor_statuses);
1463 }
1464 
1465 /*! \brief Hashing function for endpoint AOR status */
1467 
1468 /*! \brief Comparator function for endpoint AOR status */
1470 
1471 /*! \brief Find (or create) an endpoint state compositor */
1473 {
1474  struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1475 
1476  ao2_lock(sip_options_endpoint_state_compositors);
1477  endpoint_state_compositor = ao2_find(sip_options_endpoint_state_compositors,
1479  if (endpoint_state_compositor) {
1480  ao2_unlock(sip_options_endpoint_state_compositors);
1481  return endpoint_state_compositor;
1482  }
1483 
1484  endpoint_state_compositor = ao2_alloc(sizeof(*endpoint_state_compositor)
1485  + strlen(ast_sorcery_object_get_id(endpoint)) + 1,
1487  if (!endpoint_state_compositor) {
1488  ao2_unlock(sip_options_endpoint_state_compositors);
1489  return NULL;
1490  }
1491 
1492  /*
1493  * NOTE: The endpoint_state_compositor->aor_statuses container is
1494  * externally protected by the endpoint_state_compositor lock.
1495  */
1496  endpoint_state_compositor->aor_statuses = ao2_container_alloc_hash(
1498  sip_options_endpoint_aor_status_hash_fn, NULL,
1499  sip_options_endpoint_aor_status_cmp_fn);
1500  if (!endpoint_state_compositor->aor_statuses) {
1501  ao2_unlock(sip_options_endpoint_state_compositors);
1502  ao2_ref(endpoint_state_compositor, -1);
1503  return NULL;
1504  }
1505 
1506  strcpy(endpoint_state_compositor->name, ast_sorcery_object_get_id(endpoint)); /* SAFE */
1507 
1508  ao2_link_flags(sip_options_endpoint_state_compositors, endpoint_state_compositor,
1509  OBJ_NOLOCK);
1510  ao2_unlock(sip_options_endpoint_state_compositors);
1511 
1512  return endpoint_state_compositor;
1513 }
1514 
1515 /*! \brief Task details for adding an AOR to an endpoint state compositor */
1517  /*! \brief The AOR options that the endpoint state compositor should be added to */
1519  /*! \brief The endpoint state compositor */
1521 };
1522 
1523 /*!
1524  * \brief Task which adds an AOR to an endpoint state compositor
1525  * \note Run by aor_options->serializer
1526  */
1528 {
1530 
1531  ast_debug(3, "Adding endpoint compositor '%s' to AOR '%s'\n",
1532  task_data->endpoint_state_compositor->name, task_data->aor_options->name);
1533 
1534  ao2_ref(task_data->endpoint_state_compositor, +1);
1535  if (AST_VECTOR_APPEND(&task_data->aor_options->compositors,
1536  task_data->endpoint_state_compositor)) {
1537  /* Failed to add so no need to update the endpoint status. Nothing changed. */
1538  ao2_ref(task_data->endpoint_state_compositor, -1);
1539  return 0;
1540  }
1541 
1542  ao2_lock(task_data->endpoint_state_compositor);
1544  task_data->aor_options->name,
1545  task_data->aor_options->available ? AVAILABLE : UNAVAILABLE);
1547 
1548  return 0;
1549 }
1550 
1551 /*!
1552  * \brief Task which adds removes an AOR from an endpoint state compositor
1553  * \note Run by aor_options->serializer
1554  */
1556 {
1558  int i;
1559 
1560  ast_debug(3, "Removing endpoint compositor '%s' from AOR '%s'\n",
1561  task_data->endpoint_state_compositor->name,
1562  task_data->aor_options->name);
1563 
1564  for (i = 0; i < AST_VECTOR_SIZE(&task_data->aor_options->compositors); ++i) {
1565  struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1566 
1567  endpoint_state_compositor = AST_VECTOR_GET(&task_data->aor_options->compositors, i);
1568  if (endpoint_state_compositor != task_data->endpoint_state_compositor) {
1569  continue;
1570  }
1571 
1572  AST_VECTOR_REMOVE(&task_data->aor_options->compositors, i, 0);
1573  ao2_ref(endpoint_state_compositor, -1);
1574  break;
1575  }
1576 
1577  return 0;
1578 }
1579 
1580 /*!
1581  * \brief Synchronize an endpoint with our local state
1582  * \note Run by management_serializer
1583  */
1584 static int sip_options_synchronize_endpoint(void *obj, void *arg, int flags)
1585 {
1586  struct ast_sip_endpoint *endpoint = obj;
1587  struct ast_sip_aor *aor = arg;
1588  char *aors;
1589  char *aor_name;
1590  struct sip_options_endpoint_compositor_task_data task_data = { NULL, };
1591 
1592  if (ast_strlen_zero(endpoint->aors)) {
1593  /* There are no AORs, so really... who the heck knows */
1594  ast_debug(3, "Endpoint '%s' is not interested in any AORs so not creating endpoint state compositor\n",
1595  ast_sorcery_object_get_id(endpoint));
1596  return 0;
1597  }
1598 
1599  ast_debug(3, "Synchronizing endpoint '%s' with AORs '%s'\n",
1600  ast_sorcery_object_get_id(endpoint), endpoint->aors);
1601 
1602  aors = ast_strdupa(endpoint->aors);
1603  while ((aor_name = ast_strip(strsep(&aors, ",")))) {
1604  if (ast_strlen_zero(aor_name)) {
1605  continue;
1606  }
1607  if (aor && strcasecmp(ast_sorcery_object_get_id(aor), aor_name)) {
1608  ast_debug(3, "Filtered AOR '%s' on endpoint '%s' as we are looking for '%s'\n",
1609  aor_name, ast_sorcery_object_get_id(endpoint),
1611  continue;
1612  }
1613 
1614  task_data.aor_options = ao2_find(sip_options_aors, aor_name, OBJ_SEARCH_KEY);
1615  if (!task_data.aor_options) {
1616  /*
1617  * They have referenced an invalid AOR. If that's all they've
1618  * done we will set them to offline at the end.
1619  */
1620  ast_debug(3, "Endpoint '%s' referenced invalid AOR '%s'\n",
1621  ast_sorcery_object_get_id(endpoint), aor_name);
1622  continue;
1623  }
1624 
1625  if (!task_data.endpoint_state_compositor) {
1626  /*
1627  * We create an endpoint state compositor only after we know
1628  * for sure we need it.
1629  */
1630  task_data.endpoint_state_compositor =
1632  if (!task_data.endpoint_state_compositor) {
1634  "Could not create endpoint state compositor for '%s', endpoint state will be incorrect\n",
1635  ast_sorcery_object_get_id(endpoint));
1636  ao2_ref(task_data.aor_options, -1);
1639  return 0;
1640  }
1641  }
1642 
1643  /* We use a synchronous task so that we don't flood the system */
1646 
1647  ao2_ref(task_data.aor_options, -1);
1648 
1649  /*
1650  * If we filtered on a specific AOR name then the endpoint can
1651  * only reference it once so break early.
1652  */
1653  if (aor) {
1654  break;
1655  }
1656  }
1657 
1658  if (task_data.endpoint_state_compositor) {
1659  /*
1660  * If an endpoint state compositor is present determine the current state
1661  * of the endpoint and update it.
1662  */
1664  task_data.endpoint_state_compositor->active = 1;
1668 
1669  ao2_ref(task_data.endpoint_state_compositor, -1);
1670  } else if (!aor) {
1671  /* If no explicit AOR is specified we are updating the endpoint itself, so then set
1672  * it to offline if no endpoint compositor exists as they referenced an invalid AOR
1673  * or none at all
1674  */
1675  ast_debug(3, "Endpoint '%s' has no AORs feeding it, setting it to offline state as default\n",
1676  ast_sorcery_object_get_id(endpoint));
1679  }
1680 
1681  return 0;
1682 }
1683 
1684 /*!
1685  * \brief Task which removes an AOR from all of the ESCs it is reporting to
1686  * \note Run by aor_options->serializer
1687  */
1688 static int sip_options_aor_remove_task(void *obj)
1689 {
1690  struct sip_options_aor *aor_options = obj;
1691 
1693 
1694  if (aor_options->sched_task) {
1695  ast_sip_sched_task_cancel(aor_options->sched_task);
1696  ao2_ref(aor_options->sched_task, -1);
1697  aor_options->sched_task = NULL;
1698  }
1699 
1700  return 0;
1701 }
1702 
1703 /*!
1704  * \brief Callback which removes any unused AORs that remained after reloading
1705  * \note Run by management_serializer
1706  */
1707 static int sip_options_unused_aor(void *obj, void *arg, int flags)
1708 {
1709  struct sip_options_aor *aor_options = obj;
1710 
1711  ast_debug(3, "AOR '%s' is no longer configured, removing it\n", aor_options->name);
1712 
1714  aor_options);
1715  ao2_unlink(sip_options_aors, aor_options);
1716 
1717  return CMP_MATCH;
1718 }
1719 
1720 /*!
1721  * \brief Callback function used to unlink and remove event state compositors that have no AORs feeding them
1722  * \note Run by management_serializer
1723  */
1724 static int sip_options_unused_endpoint_state_compositor(void *obj, void *arg, int flags)
1725 {
1726  struct sip_options_endpoint_state_compositor *endpoint_state_compositor = obj;
1727 
1728  if (ao2_container_count(endpoint_state_compositor->aor_statuses)) {
1729  return 0;
1730  }
1731 
1732  /* No AORs are feeding this endpoint state compositor */
1733  ast_sip_persistent_endpoint_update_state(endpoint_state_compositor->name,
1735 
1736  return CMP_MATCH;
1737 }
1738 
1739 /*! \brief Structure which contains information required to synchronize */
1741  /*! \brief Whether this is a reload or not */
1742  int reload;
1743 };
1744 
1745 /*!
1746  * \brief Task to synchronize our local container of AORs and endpoint state compositors with the current configuration
1747  * \note Run by management_serializer
1748  */
1749 static int sip_options_synchronize_task(void *obj)
1750 {
1752  struct ao2_container *existing = NULL;
1753  struct ao2_container *objects;
1754 
1755  /*
1756  * When reloading we keep track of the existing AORs so we can
1757  * terminate old ones that are no longer referenced or used.
1758  */
1759  if (task_data->reload) {
1760  existing = ao2_container_clone(sip_options_aors, 0);
1761  if (!existing) {
1762  return 0;
1763  }
1764  }
1765 
1768  if (objects) {
1769  /* Go through the returned AORs and synchronize with our local state */
1771  ao2_ref(objects, -1);
1772  }
1773 
1774  /*
1775  * Any AORs remaining in existing are no longer referenced by
1776  * the current container of AORs we retrieved, so remove them.
1777  */
1778  if (existing) {
1781  ao2_ref(existing, -1);
1782  }
1783 
1784  objects = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "endpoint",
1786  if (objects) {
1787  /* Go through the provided endpoints and update AORs */
1789  ao2_ref(objects, -1);
1790  }
1791 
1792  /*
1793  * All endpoint state compositors that don't have any AORs
1794  * feeding them information can be removed. If they end
1795  * up getting needed later they'll just be recreated.
1796  */
1797  ao2_callback(sip_options_endpoint_state_compositors,
1800 
1801  return 0;
1802 }
1803 
1804 /*! \brief Synchronize our local container of AORs and endpoint state compositors with the current configuration */
1806 {
1807  struct sip_options_synchronize_task_data task_data = {
1808  .reload = reload,
1809  };
1810 
1812  &task_data);
1813 }
1814 
1815 /*!
1816  * \brief Unlink AORs feeding the endpoint status compositor
1817  * \note Run by management_serializer
1818  */
1820  struct sip_options_endpoint_state_compositor *endpoint_state_compositor)
1821 {
1822  struct ao2_iterator it_aor_statuses;
1823  struct sip_options_endpoint_aor_status *aor_status;
1824  struct sip_options_endpoint_compositor_task_data task_data = {
1826  };
1827 
1828  ao2_lock(endpoint_state_compositor);
1829  endpoint_state_compositor->active = 0;
1830 
1831  /* Unlink AOR feeders pointing to endpoint */
1832  it_aor_statuses = ao2_iterator_init(endpoint_state_compositor->aor_statuses, 0);
1833  for (; (aor_status = ao2_iterator_next(&it_aor_statuses)); ao2_ref(aor_status, -1)) {
1834  task_data.aor_options = ao2_find(sip_options_aors, aor_status->name,
1835  OBJ_SEARCH_KEY);
1836  if (!task_data.aor_options) {
1837  continue;
1838  }
1839 
1840  ast_debug(3, "Removing endpoint state compositor '%s' from AOR '%s'\n",
1841  ast_sorcery_object_get_id(endpoint), aor_status->name);
1842  ao2_unlock(endpoint_state_compositor);
1845  ao2_lock(endpoint_state_compositor);
1846  ao2_ref(task_data.aor_options, -1);
1847  }
1848  ao2_iterator_destroy(&it_aor_statuses);
1849 
1850  /*
1851  * We do not need to remove the AOR feeder status memory from the
1852  * aor_statuses container. The endpoint_state_compositor is about
1853  * to die and do it for us.
1854  */
1855 
1856  ao2_unlock(endpoint_state_compositor);
1857 }
1858 
1859 /*!
1860  * \brief Task to delete an endpoint from the known universe
1861  * \note Run by management_serializer
1862  */
1864 {
1865  struct ast_sip_endpoint *endpoint = obj;
1866  struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1867 
1868  endpoint_state_compositor = ao2_find(sip_options_endpoint_state_compositors,
1870  if (!endpoint_state_compositor) {
1871  return 0;
1872  }
1873 
1874  ast_debug(3, "Endpoint '%s' has been deleted, removing endpoint state compositor from AORs\n",
1875  ast_sorcery_object_get_id(endpoint));
1876  sip_options_endpoint_unlink_aor_feeders(endpoint, endpoint_state_compositor);
1877  ao2_ref(endpoint_state_compositor, -1);
1878 
1879  return 0;
1880 }
1881 
1882 /*! \brief Observer callback invoked on endpoint deletion */
1883 static void endpoint_observer_deleted(const void *obj)
1884 {
1885  ast_sip_push_task_wait_serializer(management_serializer,
1887 }
1888 
1889 /*!
1890  * \brief Task to synchronize the endpoint
1891  * \note Run by management_serializer
1892  */
1894 {
1895  struct ast_sip_endpoint *endpoint = obj;
1896  struct sip_options_endpoint_state_compositor *endpoint_state_compositor;
1897 
1898  ast_debug(3, "Endpoint '%s' has been created or modified, updating state\n",
1899  ast_sorcery_object_get_id(endpoint));
1900 
1901  endpoint_state_compositor = ao2_find(sip_options_endpoint_state_compositors,
1903  if (endpoint_state_compositor) {
1904  /* Unlink the AORs currently feeding the endpoint. */
1905  sip_options_endpoint_unlink_aor_feeders(endpoint, endpoint_state_compositor);
1906  ao2_ref(endpoint_state_compositor, -1);
1907  }
1908 
1909  /* Connect the AORs that now feed the endpoint. */
1910  sip_options_synchronize_endpoint(endpoint, NULL, 0);
1911  return 0;
1912 }
1913 
1914 /*! \brief Observer callback invoked on endpoint creation or modification */
1915 static void endpoint_observer_modified(const void *obj)
1916 {
1917  ast_sip_push_task_wait_serializer(management_serializer,
1919 }
1920 
1921 /*! \brief Observer callbacks for endpoints */
1924  .updated = endpoint_observer_modified,
1925  .deleted = endpoint_observer_deleted,
1926 };
1927 
1928 /*!
1929  * \brief Task to synchronize an AOR with our local state
1930  * \note Run by aor_options->serializer
1931  */
1932 static int sip_options_update_aor_task(void *obj)
1933 {
1935  int available = task_data->aor_options->available;
1936 
1937  ast_debug(3, "Individually updating AOR '%s' with current state of configuration and world\n",
1938  task_data->aor_options->name);
1939 
1940  sip_options_apply_aor_configuration(task_data->aor_options, task_data->aor,
1941  task_data->added);
1942 
1943  if (!available && task_data->aor_options->available) {
1944  ast_debug(3, "After modifying AOR '%s' it has now become available\n",
1945  task_data->aor_options->name);
1947  } else if (available && !task_data->aor_options->available) {
1948  ast_debug(3, "After modifying AOR '%s' it has become unavailable\n",
1949  task_data->aor_options->name);
1951  }
1952 
1953  return 0;
1954 }
1955 
1956 /*!
1957  * \brief Task to synchronize the AOR
1958  * \note Run by management_serializer
1959  */
1961 {
1962  struct ast_sip_aor *aor = obj;
1963  struct sip_options_aor *aor_options;
1964 
1965  aor_options = ao2_find(sip_options_aors, ast_sorcery_object_get_id(aor),
1966  OBJ_SEARCH_KEY);
1967  if (!aor_options) {
1968  struct ao2_container *endpoints;
1969 
1970  aor_options = sip_options_aor_alloc(aor);
1971  if (!aor_options) {
1972  return 0;
1973  }
1974 
1975  /*
1976  * This is a newly added AOR and we need to establish any
1977  * endpoint state compositors that may reference only the
1978  * AOR. If these need to be updated later then they'll
1979  * be done by modifying the endpoint or issuing a reload.
1980  */
1981  sip_options_apply_aor_configuration(aor_options, aor, 1);
1982  ao2_link(sip_options_aors, aor_options);
1983 
1984  /*
1985  * Using LIKE doesn't seem to work very well with non-realtime so we
1986  * fetch everything right now and do a filter on our side.
1987  */
1990  if (endpoints) {
1992  ao2_ref(endpoints, -1);
1993  }
1994  } else {
1995  struct sip_options_synchronize_aor_task_data task_data = {
1997  .aor = aor,
1998  };
1999 
2000  /*
2001  * If this AOR was modified we have to do our work in its serializer
2002  * instead of this thread to ensure that things aren't modified by
2003  * multiple threads.
2004  */
2006  sip_options_update_aor_task, &task_data);
2007  }
2008 
2009  ao2_ref(aor_options, -1);
2010 
2011  return 0;
2012 }
2013 
2014 /*! \brief Observer callback invoked on AOR creation or modification */
2015 static void aor_observer_modified(const void *obj)
2016 {
2017  ast_sip_push_task_wait_serializer(management_serializer,
2019 }
2020 
2021 /*!
2022  * \brief Task to delete an AOR from the known universe
2023  * \note Run by management_serializer
2024  */
2026 {
2027  struct ast_sip_aor *aor = obj;
2028  struct sip_options_aor *aor_options;
2029 
2030  aor_options = ao2_find(sip_options_aors, ast_sorcery_object_get_id(aor),
2032  if (!aor_options) {
2033  return 0;
2034  }
2035 
2036  ast_debug(3, "AOR '%s' has been deleted, removing it\n", aor_options->name);
2037 
2039  aor_options);
2040  ao2_ref(aor_options, -1);
2041 
2042  return 0;
2043 }
2044 
2045 /*! \brief Observer callback invoked on AOR deletion */
2046 static void aor_observer_deleted(const void *obj)
2047 {
2048  ast_sip_push_task_wait_serializer(management_serializer,
2050 }
2051 
2052 /*! \brief Observer callbacks for AORs */
2055  .updated = aor_observer_modified,
2056  .deleted = aor_observer_deleted,
2057 };
2058 
2059 /*! \brief Task details for adding an AOR to an endpoint state compositor */
2061  /*! \brief The AOR options that the contact is referring to */
2063  /*! \brief The contact itself */
2065 };
2066 
2067 
2068 /*!
2069  * \brief Check if the contact qualify options are different than local aor qualify options
2070  */
2071 static int has_qualify_changed (const struct ast_sip_contact *contact, const struct sip_options_aor *aor_options)
2072 {
2073  if (!contact) {
2074  return 0;
2075  }
2076 
2077  if (!aor_options) {
2078  if (contact->qualify_frequency) {
2079  return 1;
2080  }
2081  } else if (contact->qualify_frequency != aor_options->qualify_frequency
2082  || contact->authenticate_qualify != aor_options->authenticate_qualify
2083  || ((int)(contact->qualify_timeout * 1000)) != ((int)(aor_options->qualify_timeout * 1000))) {
2084  return 1;
2085  }
2086 
2087  return 0;
2088 }
2089 
2090 /*!
2091  * \brief Task which adds a dynamic contact to an AOR
2092  * \note Run by aor_options->serializer
2093  */
2094 static int sip_options_contact_add_task(void *obj)
2095 {
2097  struct ast_sip_contact_status *contact_status;
2098 
2099  ao2_link(task_data->aor_options->dynamic_contacts, task_data->contact);
2100  ao2_link(task_data->aor_options->contacts, task_data->contact);
2101 
2102  contact_status = ast_res_pjsip_find_or_create_contact_status(task_data->contact);
2103  ao2_cleanup(contact_status);
2104 
2105  if (task_data->aor_options->qualify_frequency) {
2106  /* There will always be a contact here, and we need to immediately schedule
2107  * a qualify so that contacts are not waiting for the qualify_frequency
2108  * timer duration before qualifying.
2109  */
2110  ast_debug(3, "Starting scheduled callback on AOR '%s' for qualifying as there is now a contact on it\n",
2111  task_data->aor_options->name);
2112  /*
2113  * We immediately schedule the initial qualify so that we get
2114  * reachable/unreachable as soon as possible. Realistically
2115  * since they pretty much just registered they should be
2116  * reachable.
2117  */
2118  if (task_data->aor_options->sched_task) {
2120  ao2_ref(task_data->aor_options->sched_task, -1);
2121  task_data->aor_options->sched_task = NULL;
2122  }
2126  task_data->aor_options,
2128  if (!task_data->aor_options->sched_task) {
2129  ast_log(LOG_ERROR, "Unable to schedule qualify for contacts of AOR '%s'\n",
2130  task_data->aor_options->name);
2131  }
2132  } else {
2133  /*
2134  * If this was the first contact added to a non-qualified AOR then
2135  * it should become available.
2136  */
2137  task_data->aor_options->available =
2139  if (task_data->aor_options->available == 1) {
2140  ast_debug(3, "An unqualified contact has been added to AOR '%s' so it is now available\n",
2141  task_data->aor_options->name);
2143  AVAILABLE);
2144  }
2145  }
2146 
2147  return 0;
2148 }
2149 
2150 /*!
2151  * \brief Task to add a dynamic contact to an AOR in its serializer
2152  * \note Run by management_serializer
2153  */
2155 {
2156  struct sip_options_contact_observer_task_data task_data;
2157 
2158  task_data.contact = obj;
2159  task_data.aor_options = ao2_find(sip_options_aors, task_data.contact->aor,
2160  OBJ_SEARCH_KEY);
2161 
2162  if (has_qualify_changed(task_data.contact, task_data.aor_options)) {
2163  struct ast_sip_aor *aor;
2164 
2166  task_data.contact->aor);
2167  if (aor) {
2168  ast_debug(3, "AOR '%s' qualify options have been modified. Synchronize an AOR local state\n",
2169  task_data.contact->aor);
2171  ao2_ref(aor, -1);
2172  }
2173  }
2174 
2175  if (!task_data.aor_options) {
2176  return 0;
2177  }
2178 
2180  sip_options_contact_add_task, &task_data);
2181  ao2_ref(task_data.aor_options, -1);
2182 
2183  return 0;
2184 }
2185 
2186 /*! \brief Observer callback invoked on contact creation */
2187 static void contact_observer_created(const void *obj)
2188 {
2189  ast_sip_push_task_wait_serializer(management_serializer,
2191 }
2192 
2193 /*!
2194  * \brief Task which updates a dynamic contact to an AOR
2195  * \note Run by aor_options->serializer
2196  */
2197 static int sip_options_contact_update_task(void *obj)
2198 {
2200  struct ast_sip_contact_status *contact_status;
2201 
2202  contact_status = ast_sip_get_contact_status(task_data->contact);
2203  if (contact_status) {
2204  switch (contact_status->status) {
2205  case CREATED:
2206  case UNAVAILABLE:
2207  case AVAILABLE:
2208  case UNKNOWN:
2209  /* Refresh the ContactStatus AMI events. */
2210  sip_options_contact_status_update(contact_status);
2211  break;
2212  case REMOVED:
2213  break;
2214  }
2215  ao2_ref(contact_status, -1);
2216  }
2217 
2218  ao2_ref(task_data->contact, -1);
2219  ao2_ref(task_data->aor_options, -1);
2220  ast_free(task_data);
2221  return 0;
2222 }
2223 
2224 /*! \brief Observer callback invoked on contact update */
2225 static void contact_observer_updated(const void *obj)
2226 {
2227  const struct ast_sip_contact *contact = obj;
2228  struct sip_options_aor *aor_options = ao2_find(sip_options_aors, contact->aor, OBJ_SEARCH_KEY);
2229 
2230  if (has_qualify_changed(contact, aor_options)) {
2231  struct ast_sip_aor *aor;
2232 
2234  contact->aor);
2235  if (aor) {
2236  ast_debug(3, "AOR '%s' qualify options have been modified. Synchronize an AOR local state\n",
2237  contact->aor);
2238  ast_sip_push_task_wait_serializer(management_serializer,
2240  ao2_ref(aor, -1);
2241  }
2242  }
2243 
2246 
2247  task_data = ast_malloc(sizeof(*task_data));
2248  if (!task_data) {
2249  ao2_ref(aor_options, -1);
2250  return;
2251  }
2252 
2253  task_data->contact = (struct ast_sip_contact *) contact;
2254  /* task_data takes ownership of aor_options and will take care of releasing the ref */
2255  task_data->aor_options = aor_options;
2256 
2257  ao2_ref(task_data->contact, +1);
2258  if (ast_sip_push_task(task_data->aor_options->serializer,
2259  sip_options_contact_update_task, task_data)) {
2260  ao2_ref(task_data->contact, -1);
2261  ao2_ref(task_data->aor_options, -1);
2262  ast_free(task_data);
2263  }
2264  } else {
2265  ao2_cleanup(aor_options);
2266  }
2267 }
2268 
2269 /*!
2270  * \brief Task which deletes a dynamic contact from an AOR
2271  * \note Run by aor_options->serializer
2272  */
2273 static int sip_options_contact_delete_task(void *obj)
2274 {
2276 
2277  ao2_find(task_data->aor_options->dynamic_contacts, task_data->contact,
2279  ao2_find(task_data->aor_options->contacts, task_data->contact,
2281 
2282  sip_options_remove_contact_status(task_data->aor_options, task_data->contact);
2283 
2284  if (task_data->aor_options->qualify_frequency) {
2285  /* If this is the last contact then we need to stop the scheduled callback */
2286  if (!ao2_container_count(task_data->aor_options->contacts)) {
2287  ast_debug(3, "Terminating scheduled callback on AOR '%s' as there are no contacts to qualify\n",
2288  task_data->aor_options->name);
2289  if (task_data->aor_options->sched_task) {
2291  ao2_ref(task_data->aor_options->sched_task, -1);
2292  task_data->aor_options->sched_task = NULL;
2293  }
2294  }
2295  } else {
2296  task_data->aor_options->available =
2298  if (!task_data->aor_options->available) {
2299  ast_debug(3, "An unqualified contact has been removed from AOR '%s' leaving no remaining contacts\n",
2300  task_data->aor_options->name);
2302  UNAVAILABLE);
2303  }
2304  }
2305 
2306  return 0;
2307 }
2308 
2309 /*!
2310  * \brief Task to delete a contact from an AOR in its serializer
2311  * \note Run by management_serializer
2312  */
2314 {
2315  struct sip_options_contact_observer_task_data task_data;
2316 
2317  task_data.contact = obj;
2318  task_data.aor_options = ao2_find(sip_options_aors, task_data.contact->aor,
2319  OBJ_SEARCH_KEY);
2320  if (!task_data.aor_options) {
2321  /* For contacts that are deleted we don't really care if there is no AOR locally */
2322  return 0;
2323  }
2324 
2326  sip_options_contact_delete_task, &task_data);
2327  ao2_ref(task_data.aor_options, -1);
2328 
2329  return 0;
2330 }
2331 
2332 /*! \brief Observer callback invoked on contact deletion */
2333 static void contact_observer_deleted(const void *obj)
2334 {
2335  ast_sip_push_task_wait_serializer(management_serializer,
2337 }
2338 
2339 /*! \brief Observer callbacks for contacts */
2342  .updated = contact_observer_updated,
2343  .deleted = contact_observer_deleted,
2344 };
2345 
2346 static char *cli_qualify(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2347 {
2348  RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2349  const char *endpoint_name;
2350  char *aors;
2351  char *aor_name;
2352 
2353  switch (cmd) {
2354  case CLI_INIT:
2355  e->command = "pjsip qualify";
2356  e->usage =
2357  "Usage: pjsip qualify <endpoint>\n"
2358  " Send a SIP OPTIONS request to all contacts on the endpoint.\n";
2359  return NULL;
2360  case CLI_GENERATE:
2361  return NULL;
2362  }
2363 
2364  if (a->argc != 3) {
2365  return CLI_SHOWUSAGE;
2366  }
2367 
2368  endpoint_name = a->argv[2];
2369 
2370  endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2371  endpoint_name);
2372  if (!endpoint) {
2373  ast_cli(a->fd, "Unable to retrieve endpoint %s\n", endpoint_name);
2374  return CLI_FAILURE;
2375  }
2376 
2377  if (ast_strlen_zero(endpoint->aors)) {
2378  ast_cli(a->fd, "No AORs configured for endpoint '%s'\n", endpoint_name);
2379  return CLI_FAILURE;
2380  }
2381 
2382  aors = ast_strdupa(endpoint->aors);
2383  while ((aor_name = ast_strip(strsep(&aors, ",")))) {
2384  struct sip_options_aor *aor_options;
2385 
2386  aor_options = ao2_find(sip_options_aors, aor_name, OBJ_SEARCH_KEY);
2387  if (!aor_options) {
2388  continue;
2389  }
2390 
2391  ast_cli(a->fd, "Qualifying AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2393  aor_options);
2394  ao2_ref(aor_options, -1);
2395  }
2396 
2397  return CLI_SUCCESS;
2398 }
2399 
2400 static struct ao2_container *get_all_contacts(void)
2401 {
2402  struct ao2_container *contacts;
2403 
2404  contacts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "contact",
2406 
2407  return contacts;
2408 }
2409 
2410 static int sip_contact_to_ami(const struct ast_sip_contact *contact,
2411  struct ast_str **buf)
2412 {
2413  return ast_sip_sorcery_object_to_ami(contact, buf);
2414 }
2415 
2416 static int format_ami_contactlist_handler(void *obj, void *arg, int flags)
2417 {
2418  struct ast_sip_contact *contact = obj;
2419  struct ast_sip_ami *ami = arg;
2420  struct ast_str *buf;
2422 
2423  buf = ast_sip_create_ami_event("ContactList", ami);
2424  if (!buf) {
2425  return CMP_STOP;
2426  }
2427 
2428  if (sip_contact_to_ami(contact, &buf)) {
2429  ast_free(buf);
2430  return CMP_STOP;
2431  }
2432 
2433  /* Add extra info */
2434  status = ast_sip_get_contact_status(contact);
2435  ast_str_append(&buf, 0, "Status: %s\r\n",
2436  ast_sip_get_contact_status_label(status ? status->status : UNKNOWN));
2437  if (!status || status->status != AVAILABLE) {
2438  ast_str_append(&buf, 0, "RoundtripUsec: N/A\r\n");
2439  } else {
2440  ast_str_append(&buf, 0, "RoundtripUsec: %" PRId64 "\r\n", status->rtt);
2441  }
2442  ao2_cleanup(status);
2443 
2444  astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
2445 
2446  ami->count++;
2447 
2448  ast_free(buf);
2449 
2450  return 0;
2451 }
2452 
2453 static int ami_show_contacts(struct mansession *s, const struct message *m)
2454 {
2455  struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
2456  struct ao2_container *contacts;
2457 
2458  contacts = get_all_contacts();
2459  if (!contacts) {
2460  astman_send_error(s, m, "Could not get Contacts\n");
2461  return 0;
2462  }
2463 
2464  if (!ao2_container_count(contacts)) {
2465  astman_send_error(s, m, "No Contacts found\n");
2466  ao2_ref(contacts, -1);
2467  return 0;
2468  }
2469 
2470  astman_send_listack(s, m, "A listing of Contacts follows, presented as ContactList events",
2471  "start");
2472 
2474 
2475  astman_send_list_complete_start(s, m, "ContactListComplete", ami.count);
2477 
2478  ao2_ref(contacts, -1);
2479 
2480  return 0;
2481 }
2482 
2483 static char *cli_show_qualify_endpoint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2484 {
2485  RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2486  const char *endpoint_name;
2487  char *aors;
2488  char *aor_name;
2489 
2490  switch (cmd) {
2491  case CLI_INIT:
2492  e->command = "pjsip show qualify endpoint";
2493  e->usage =
2494  "Usage: pjsip show qualify endpoint <id>\n"
2495  " Show the current qualify options for all Aors on the PJSIP endpoint.\n";
2496  return NULL;
2497  case CLI_GENERATE:
2498  return NULL;
2499  }
2500 
2501  if (a->argc != 5) {
2502  return CLI_SHOWUSAGE;
2503  }
2504 
2505  endpoint_name = a->argv[4];
2506 
2507  endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2508  endpoint_name);
2509  if (!endpoint) {
2510  ast_cli(a->fd, "Unable to retrieve endpoint %s\n", endpoint_name);
2511  return CLI_FAILURE;
2512  }
2513 
2514  if (ast_strlen_zero(endpoint->aors)) {
2515  ast_cli(a->fd, "No AORs configured for endpoint '%s'\n", endpoint_name);
2516  return CLI_FAILURE;
2517  }
2518 
2519  aors = ast_strdupa(endpoint->aors);
2520  while ((aor_name = ast_strip(strsep(&aors, ",")))) {
2521  struct sip_options_aor *aor_options;
2522 
2523  aor_options = ao2_find(sip_options_aors, aor_name, OBJ_SEARCH_KEY);
2524  if (!aor_options) {
2525  continue;
2526  }
2527 
2528  ast_cli(a->fd, " * AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2529  ast_cli(a->fd, " Qualify frequency : %d sec\n", aor_options->qualify_frequency);
2530  ast_cli(a->fd, " Qualify timeout : %d ms\n", (int)(aor_options->qualify_timeout / 1000));
2531  ast_cli(a->fd, " Authenticate qualify : %s\n", aor_options->authenticate_qualify?"yes":"no");
2532  ast_cli(a->fd, "\n");
2533  ao2_ref(aor_options, -1);
2534  }
2535 
2536  return CLI_SUCCESS;
2537 }
2538 
2539 static char *cli_show_qualify_aor(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2540 {
2541  struct sip_options_aor *aor_options;
2542  const char *aor_name;
2543 
2544  switch (cmd) {
2545  case CLI_INIT:
2546  e->command = "pjsip show qualify aor";
2547  e->usage =
2548  "Usage: pjsip show qualify aor <id>\n"
2549  " Show the PJSIP Aor current qualify options.\n";
2550  return NULL;
2551  case CLI_GENERATE:
2552  return NULL;
2553  }
2554 
2555  if (a->argc != 5) {
2556  return CLI_SHOWUSAGE;
2557  }
2558 
2559  aor_name = a->argv[4];
2560 
2561  aor_options = ao2_find(sip_options_aors, aor_name, OBJ_SEARCH_KEY);
2562  if (!aor_options) {
2563  ast_cli(a->fd, "Unable to retrieve aor '%s' qualify options\n", aor_name);
2564  return CLI_FAILURE;
2565  }
2566 
2567  ast_cli(a->fd, " * AOR '%s'\n", aor_name);
2568  ast_cli(a->fd, " Qualify frequency : %d sec\n", aor_options->qualify_frequency);
2569  ast_cli(a->fd, " Qualify timeout : %d ms\n", (int)(aor_options->qualify_timeout / 1000));
2570  ast_cli(a->fd, " Authenticate qualify : %s\n", aor_options->authenticate_qualify?"yes":"no");
2571  ao2_ref(aor_options, -1);
2572 
2573  return CLI_SUCCESS;
2574 }
2575 
2576 static char *cli_reload_qualify_endpoint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2577 {
2578  RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2579  const char *endpoint_name;
2580  char *aors;
2581  char *aor_name;
2582 
2583  switch (cmd) {
2584  case CLI_INIT:
2585  e->command = "pjsip reload qualify endpoint";
2586  e->usage =
2587  "Usage: pjsip reload qualify endpoint <id>\n"
2588  " Synchronize the qualify options for all Aors on the PJSIP endpoint.\n";
2589  return NULL;
2590  case CLI_GENERATE:
2591  return NULL;
2592  }
2593 
2594  if (a->argc != 5) {
2595  return CLI_SHOWUSAGE;
2596  }
2597 
2598  endpoint_name = a->argv[4];
2599 
2600  endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2601  endpoint_name);
2602  if (!endpoint) {
2603  ast_cli(a->fd, "Unable to retrieve endpoint %s\n", endpoint_name);
2604  return CLI_FAILURE;
2605  }
2606 
2607  if (ast_strlen_zero(endpoint->aors)) {
2608  ast_cli(a->fd, "No AORs configured for endpoint '%s'\n", endpoint_name);
2609  return CLI_FAILURE;
2610  }
2611 
2612  aors = ast_strdupa(endpoint->aors);
2613  while ((aor_name = ast_strip(strsep(&aors, ",")))) {
2614  struct ast_sip_aor *aor;
2615 
2616  aor = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "aor", aor_name);
2617  if (!aor) {
2618  continue;
2619  }
2620 
2621  ast_cli(a->fd, "Synchronizing AOR '%s' on endpoint '%s'\n", aor_name, endpoint_name);
2622  ast_sip_push_task_wait_serializer(management_serializer,
2624  ao2_ref(aor, -1);
2625  }
2626 
2627  return CLI_SUCCESS;
2628 }
2629 
2630 static char *cli_reload_qualify_aor(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2631 {
2632  struct ast_sip_aor *aor;
2633  const char *aor_name;
2634 
2635  switch (cmd) {
2636  case CLI_INIT:
2637  e->command = "pjsip reload qualify aor";
2638  e->usage =
2639  "Usage: pjsip reload qualify aor <id>\n"
2640  " Synchronize the PJSIP Aor qualify options.\n";
2641  return NULL;
2642  case CLI_GENERATE:
2643  return NULL;
2644  }
2645 
2646  if (a->argc != 5) {
2647  return CLI_SHOWUSAGE;
2648  }
2649 
2650  aor_name = a->argv[4];
2651 
2652  aor = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "aor", aor_name);
2653  if (!aor) {
2654  ast_cli(a->fd, "Unable to retrieve aor '%s'\n", aor_name);
2655  return CLI_FAILURE;
2656  }
2657 
2658  ast_cli(a->fd, "Synchronizing AOR '%s'\n", aor_name);
2659  ast_sip_push_task_wait_serializer(management_serializer,
2661  ao2_ref(aor, -1);
2662 
2663  return CLI_SUCCESS;
2664 }
2665 
2666 static int ami_sip_qualify(struct mansession *s, const struct message *m)
2667 {
2668  const char *endpoint_name = astman_get_header(m, "Endpoint");
2669  RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
2670  char *aors;
2671  char *aor_name;
2672 
2673  if (ast_strlen_zero(endpoint_name)) {
2674  astman_send_error(s, m, "Endpoint parameter missing.");
2675  return 0;
2676  }
2677 
2678  endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2679  endpoint_name);
2680  if (!endpoint) {
2681  astman_send_error(s, m, "Unable to retrieve endpoint\n");
2682  return 0;
2683  }
2684 
2685  /* send a qualify for all contacts registered with the endpoint */
2686  if (ast_strlen_zero(endpoint->aors)) {
2687  astman_send_error(s, m, "No AoRs configured for endpoint\n");
2688  return 0;
2689  }
2690 
2691  aors = ast_strdupa(endpoint->aors);
2692  while ((aor_name = ast_strip(strsep(&aors, ",")))) {
2693  struct sip_options_aor *aor_options;
2694 
2695  aor_options = ao2_find(sip_options_aors, aor_name, OBJ_SEARCH_KEY);
2696  if (!aor_options) {
2697  continue;
2698  }
2699 
2701  aor_options);
2702  ao2_ref(aor_options, -1);
2703  }
2704 
2705  astman_send_ack(s, m, "Endpoint found, will qualify");
2706  return 0;
2707 }
2708 
2709 static struct ast_cli_entry cli_options[] = {
2710  AST_CLI_DEFINE(cli_qualify, "Send an OPTIONS request to a PJSIP endpoint"),
2711  AST_CLI_DEFINE(cli_show_qualify_endpoint, "Show the current qualify options for all Aors on the PJSIP endpoint"),
2712  AST_CLI_DEFINE(cli_show_qualify_aor, "Show the PJSIP Aor current qualify options"),
2713  AST_CLI_DEFINE(cli_reload_qualify_endpoint, "Synchronize the qualify options for all Aors on the PJSIP endpoint"),
2714  AST_CLI_DEFINE(cli_reload_qualify_aor, "Synchronize the PJSIP Aor qualify options"),
2715 };
2716 
2717 int ast_sip_format_contact_ami(void *obj, void *arg, int flags)
2718 {
2719  struct ast_sip_contact_wrapper *wrapper = obj;
2720  struct ast_sip_contact *contact = wrapper->contact;
2721  struct ast_sip_ami *ami = arg;
2723  struct ast_str *buf;
2724  const struct ast_sip_endpoint *endpoint = ami->arg;
2725 
2726  buf = ast_sip_create_ami_event("ContactStatusDetail", ami);
2727  if (!buf) {
2728  return -1;
2729  }
2730 
2731  status = ast_sip_get_contact_status(contact);
2732 
2733  ast_str_append(&buf, 0, "AOR: %s\r\n", wrapper->aor_id);
2734  ast_str_append(&buf, 0, "URI: %s\r\n", contact->uri);
2735  ast_str_append(&buf, 0, "UserAgent: %s\r\n", contact->user_agent);
2736  ast_str_append(&buf, 0, "RegExpire: %ld\r\n", contact->expiration_time.tv_sec);
2737  if (!ast_strlen_zero(contact->via_addr)) {
2738  ast_str_append(&buf, 0, "ViaAddress: %s", contact->via_addr);
2739  if (contact->via_port) {
2740  ast_str_append(&buf, 0, ":%d", contact->via_port);
2741  }
2742  ast_str_append(&buf, 0, "\r\n");
2743  }
2744  if (!ast_strlen_zero(contact->call_id)) {
2745  ast_str_append(&buf, 0, "CallID: %s\r\n", contact->call_id);
2746  }
2747  ast_str_append(&buf, 0, "Status: %s\r\n",
2748  ast_sip_get_contact_status_label(status ? status->status : UNKNOWN));
2749  if (!status || status->status != AVAILABLE) {
2750  ast_str_append(&buf, 0, "RoundtripUsec: N/A\r\n");
2751  } else {
2752  ast_str_append(&buf, 0, "RoundtripUsec: %" PRId64 "\r\n", status->rtt);
2753  }
2754  ast_str_append(&buf, 0, "EndpointName: %s\r\n",
2755  endpoint ? ast_sorcery_object_get_id(endpoint) : S_OR(contact->endpoint_name, ""));
2756 
2757  ast_str_append(&buf, 0, "ID: %s\r\n", ast_sorcery_object_get_id(contact));
2758  ast_str_append(&buf, 0, "AuthenticateQualify: %d\r\n", contact->authenticate_qualify);
2759  ast_str_append(&buf, 0, "OutboundProxy: %s\r\n", contact->outbound_proxy);
2760  ast_str_append(&buf, 0, "Path: %s\r\n", contact->path);
2761  ast_str_append(&buf, 0, "QualifyFrequency: %u\r\n", contact->qualify_frequency);
2762  ast_str_append(&buf, 0, "QualifyTimeout: %.3f\r\n", contact->qualify_timeout);
2763 
2764  astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
2765  ami->count++;
2766 
2767  ast_free(buf);
2768  ao2_cleanup(status);
2769  return 0;
2770 }
2771 
2772 static int format_contact_status_for_aor(void *obj, void *arg, int flags)
2773 {
2774  struct ast_sip_aor *aor = obj;
2775 
2777 }
2778 
2779 static int format_ami_contact_status(const struct ast_sip_endpoint *endpoint,
2780  struct ast_sip_ami *ami)
2781 {
2782  ami->arg = (void *)endpoint;
2784 }
2785 
2788 };
2789 
2790 /*!
2791  * \brief Management task to clean up an AOR
2792  * \note Run by aor_options->serializer
2793  */
2794 static int sip_options_cleanup_aor_task(void *obj)
2795 {
2796  struct sip_options_aor *aor_options = obj;
2797 
2798  ast_debug(2, "Cleaning up AOR '%s' for shutdown\n", aor_options->name);
2799 
2800  aor_options->qualify_frequency = 0;
2801  if (aor_options->sched_task) {
2802  ast_sip_sched_task_cancel(aor_options->sched_task);
2803  ao2_ref(aor_options->sched_task, -1);
2804  aor_options->sched_task = NULL;
2805  }
2806  AST_VECTOR_RESET(&aor_options->compositors, ao2_cleanup);
2807 
2808  return 0;
2809 }
2810 
2811 /*!
2812  * \brief Management task to clean up the environment
2813  * \note Run by management_serializer
2814  */
2815 static int sip_options_cleanup_task(void *obj)
2816 {
2817  struct ao2_iterator it_aor;
2818  struct sip_options_aor *aor_options;
2819 
2820  if (!sip_options_aors) {
2821  /* Nothing to do */
2822  return 0;
2823  }
2824 
2825  it_aor = ao2_iterator_init(sip_options_aors, AO2_ITERATOR_UNLINK);
2826  for (; (aor_options = ao2_iterator_next(&it_aor)); ao2_ref(aor_options, -1)) {
2828  sip_options_cleanup_aor_task, aor_options);
2829  }
2830  ao2_iterator_destroy(&it_aor);
2831 
2832  return 0;
2833 }
2834 
2836 {
2837  int remaining;
2838  struct ast_taskprocessor *mgmt_serializer;
2839 
2840  ast_cli_unregister_multiple(cli_options, ARRAY_LEN(cli_options));
2841  ast_manager_unregister("PJSIPQualify");
2842  ast_manager_unregister("PJSIPShowContacts");
2843  ast_sip_unregister_endpoint_formatter(&contact_status_formatter);
2844 
2846  &contact_observer_callbacks);
2848  &aor_observer_callbacks);
2850  &endpoint_observer_callbacks);
2851 
2852  mgmt_serializer = management_serializer;
2853  management_serializer = NULL;
2854  if (mgmt_serializer) {
2856  }
2857 
2858  remaining = ast_serializer_shutdown_group_join(shutdown_group,
2860  if (remaining) {
2861  ast_log(LOG_WARNING, "Cleanup incomplete. Could not stop %d AORs.\n",
2862  remaining);
2863  }
2864  ao2_cleanup(shutdown_group);
2865  shutdown_group = NULL;
2866 
2867  if (mgmt_serializer) {
2868  ast_taskprocessor_unreference(mgmt_serializer);
2869  }
2870 
2871  ao2_cleanup(sip_options_aors);
2872  sip_options_aors = NULL;
2873  ao2_cleanup(sip_options_contact_statuses);
2874  sip_options_contact_statuses = NULL;
2875  ao2_cleanup(sip_options_endpoint_state_compositors);
2876  sip_options_endpoint_state_compositors = NULL;
2877 
2878  pjsip_endpt_unregister_module(ast_sip_get_pjsip_endpoint(), &options_module);
2879 }
2880 
2881 /*!
2882  * \brief Management task to finish setting up the environment.
2883  * \note Run by management_serializer
2884  */
2885 static int sip_options_init_task(void *mgmt_serializer)
2886 {
2887  management_serializer = mgmt_serializer;
2888 
2889  shutdown_group = ast_serializer_shutdown_group_alloc();
2890  if (!shutdown_group) {
2891  return -1;
2892  }
2893 
2895  &endpoint_observer_callbacks)) {
2896  return -1;
2897  }
2899  &aor_observer_callbacks)) {
2900  return -1;
2901  }
2903  &contact_observer_callbacks)) {
2904  return -1;
2905  }
2906 
2908 
2909  return 0;
2910 }
2911 
2913 {
2914  sip_options_contact_statuses = sip_options_contact_statuses_alloc();
2915  return sip_options_contact_statuses ? 0 : -1;
2916 }
2917 
2919 {
2920  struct ast_taskprocessor *mgmt_serializer;
2921 
2922  static const pj_str_t STR_OPTIONS = { "OPTIONS", 7 };
2923 
2924  if (reload) {
2926  return 0;
2927  }
2928 
2929  if (pjsip_endpt_register_module(ast_sip_get_pjsip_endpoint(), &options_module)
2930  != PJ_SUCCESS) {
2931  return -1;
2932  }
2933 
2934  if (pjsip_endpt_add_capability(ast_sip_get_pjsip_endpoint(), NULL, PJSIP_H_ALLOW,
2935  NULL, 1, &STR_OPTIONS) != PJ_SUCCESS) {
2937  return -1;
2938  }
2939 
2941  sip_options_aor_hash_fn, NULL, sip_options_aor_cmp_fn);
2942  if (!sip_options_aors) {
2944  return -1;
2945  }
2946  sip_options_endpoint_state_compositors =
2949  sip_options_endpoint_state_compositor_hash_fn, NULL,
2950  sip_options_endpoint_state_compositor_cmp_fn);
2951  if (!sip_options_endpoint_state_compositors) {
2953  return -1;
2954  }
2955 
2956  mgmt_serializer = ast_sip_create_serializer("pjsip/options/manage");
2957  if (!mgmt_serializer) {
2959  return -1;
2960  }
2961 
2962  /*
2963  * Set the water mark levels high because we can get a flood of
2964  * contact status updates from sip_options_synchronize() that
2965  * quickly clears on initial load or reload.
2966  */
2967  ast_taskprocessor_alert_set_levels(mgmt_serializer, -1,
2969 
2970  /*
2971  * We make sure that the environment is completely setup before we allow
2972  * any other threads to post contact_status updates to the
2973  * management_serializer.
2974  */
2976  mgmt_serializer)) {
2977  /* Set management_serializer in case pushing the task actually failed. */
2978  management_serializer = mgmt_serializer;
2980  return -1;
2981  }
2982 
2983  ast_sip_register_endpoint_formatter(&contact_status_formatter);
2985  ami_sip_qualify);
2987  ast_cli_register_multiple(cli_options, ARRAY_LEN(cli_options));
2988 
2989  return 0;
2990 }
double qualify_timeout
Definition: res_pjsip.h:387
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
static int sip_options_update_aor_task(void *obj)
Task to synchronize an AOR with our local state.
static void contact_observer_updated(const void *obj)
Observer callback invoked on contact update.
enum sip_cc_notify_state state
Definition: chan_sip.c:960
static int format_ami_contact_status(const struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami)
int authenticate_qualify
Definition: res_pjsip.h:309
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
#define AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(str)
Truncate the URI user field options string if enabled.
Definition: res_pjsip.h:3036
static struct sip_options_aor * sip_options_aor_alloc(struct ast_sip_aor *aor)
Allocator for AOR OPTIONS.
static int sip_options_contact_delete_management_task(void *obj)
Task to delete a contact from an AOR in its serializer.
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
static void sip_options_endpoint_state_compositor_dtor(void *obj)
Destructor for endpoint state compositors.
void ast_statsd_log_full_va(const char *metric_name, const char *metric_type, intmax_t value, double sample_rate,...)
Send a stat to the configured statsd server.
Definition: res_statsd.c:199
static int sip_options_endpoint_compositor_add_task(void *obj)
Task which adds an AOR to an endpoint state compositor.
void ast_taskprocessor_build_name(char *buf, unsigned int size, const char *format,...)
Build a taskprocessor name with a sequence number on the end.
enum ast_sip_contact_status_type last_status
Definition: res_pjsip.h:353
static int ami_sip_qualify(struct mansession *s, const struct message *m)
A contact&#39;s status.
Definition: res_pjsip.h:341
static const char * short_status_map[]
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
Asterisk main include file. File version handling, generic pbx functions.
int ast_shutting_down(void)
Definition: asterisk.c:1834
A SIP address of record.
Definition: res_pjsip.h:361
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 &#39;on_aor&#39; handler. ...
Definition: location.c:684
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
An entity responsible formatting endpoint information.
Definition: res_pjsip.h:2763
AO2_STRING_FIELD_HASH_FN(ast_sip_contact_status, name)
Hashing function for contact statuses.
static struct ao2_container * sip_options_contact_statuses
static struct sip_options_contact_callback_data * sip_options_contact_callback_data_alloc(struct ast_sip_contact *contact, struct sip_options_aor *aor_options)
Contact callback data allocator.
static char * cli_show_qualify_endpoint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
const ast_string_field outbound_proxy
Definition: res_pjsip.h:303
static struct ast_cli_entry cli_options[]
const ast_string_field call_id
Definition: res_pjsip.h:303
int ast_res_pjsip_preinit_options_handling(void)
static const struct ast_sorcery_observer contact_observer_callbacks
Observer callbacks for contacts.
const ast_string_field user_agent
Definition: res_pjsip.h:303
struct sip_options_aor * aor_options
The AOR options that the endpoint state compositor should be added to.
static void sip_options_apply_aor_configuration(struct sip_options_aor *aor_options, struct ast_sip_aor *aor, int is_new)
Function which applies configuration to an AOR options structure.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
struct sip_options_aor * aor_options
The AOR options that the contact is referring to.
static int sip_options_cleanup_task(void *obj)
Management task to clean up the environment.
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
static void qualify_contact_cb(void *token, pjsip_event *e)
Callback for when we get a result from a SIP OPTIONS request (a response or a timeout) ...
const ast_string_field path
Definition: res_pjsip.h:303
Structure which contains composites information for endpoint state.
Time-related functions and macros.
static int sip_options_set_contact_status_qualified(void *obj, void *arg, int flags)
Transition the contact status to qualified mode.
const struct message * m
Definition: res_pjsip.h:2741
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define ao2_container_clone(orig, flags)
Definition: astobj2.h:1430
struct ast_sip_contact_status * ast_res_pjsip_find_or_create_contact_status(const struct ast_sip_contact *contact)
int ast_sip_sched_task_cancel(struct ast_sip_sched_task *schtd)
Cancels the next invocation of a task.
static const char * status_map[]
Task data for AOR creation or updating.
static void sip_options_aor_dtor(void *obj)
Destructor function for SIP OPTIONS AORs.
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:3237
static void sip_options_synchronize(int reload)
Synchronize our local container of AORs and endpoint state compositors with the current configuration...
descriptor for a cli entry.
Definition: cli.h:171
const int argc
Definition: cli.h:160
#define LOG_WARNING
Definition: logger.h:274
const ast_string_field via_addr
Definition: res_pjsip.h:303
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
#define AST_TASKPROCESSOR_HIGH_WATER_LEVEL
Definition: taskprocessor.h:63
static int has_qualify_changed(const struct ast_sip_contact *contact, const struct sip_options_aor *aor_options)
Check if the contact qualify options are different than local aor qualify options.
int ast_sip_set_outbound_proxy(pjsip_tx_data *tdata, const char *proxy)
Set the outbound proxy for an outbound SIP message.
Definition: res_pjsip.c:5047
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
static const struct ast_sorcery_observer aor_observer_callbacks
Observer callbacks for AORs.
struct ast_serializer_shutdown_group * ast_serializer_shutdown_group_alloc(void)
Create a serializer group shutdown control object.
Definition: threadpool.c:1229
void * arg
Definition: res_pjsip.h:2745
AMI variable container.
Definition: res_pjsip.h:2737
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
void(* created)(const void *object)
Callback for when an object is created.
Definition: sorcery.h:334
Test Framework API.
Perform no matching, return all objects.
Definition: sorcery.h:123
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
Definition: sorcery.c:2459
char name[0]
The name of the endpoint.
Definition: cli.h:152
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
static char * cli_reload_qualify_endpoint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct sip_options_endpoint_state_compositor * sip_options_endpoint_state_compositor_find_or_alloc(const struct ast_sip_endpoint *endpoint)
Find (or create) an endpoint state compositor.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
unsigned int qualify_frequency
Definition: res_pjsip.h:307
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static void sip_contact_status_dtor(void *obj)
Destructor for contact statuses.
static void sip_options_endpoint_unlink_aor_feeders(struct ast_sip_endpoint *endpoint, struct sip_options_endpoint_state_compositor *endpoint_state_compositor)
Unlink AORs feeding the endpoint status compositor.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
Return all matching objects.
Definition: sorcery.h:120
const char * ast_taskprocessor_name(struct ast_taskprocessor *tps)
Return the name of the taskprocessor singleton.
static void endpoint_observer_modified(const void *obj)
Observer callback invoked on endpoint creation or modification.
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define ast_assert(a)
Definition: utils.h:710
#define ao2_link_flags(container, obj, flags)
Definition: astobj2.h:1572
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
#define ao2_unlock(a)
Definition: astobj2.h:730
static int sip_options_init_task(void *mgmt_serializer)
Management task to finish setting up the environment.
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.
Definition: res_pjsip.c:5240
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.
Definition: sorcery.c:1984
void ast_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Unregister an endpoint formatter.
Definition: res_pjsip.c:3685
int ast_taskprocessor_alert_set_levels(struct ast_taskprocessor *tps, long low_water, long high_water)
Set the high and low alert water marks of the given taskprocessor queue.
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define AST_TASKPROCESSOR_MAX_NAME
Suggested maximum taskprocessor name length (less null terminator).
Definition: taskprocessor.h:60
int ast_serializer_shutdown_group_join(struct ast_serializer_shutdown_group *shutdown_group, int timeout)
Wait for the serializers in the group to shutdown with timeout.
Definition: threadpool.c:1241
const ast_string_field uri
Definition: res_pjsip.h:347
#define ENDPOINT_STATE_COMPOSITOR_INITIAL_SIZE
The initial vector size for the endpoint state compositors on an AOR.
static pj_status_t send_options_response(pjsip_rx_data *rdata, int code)
struct ao2_container * aor_statuses
The last contributed available status of the AORs feeding this compositor.
static struct ast_sip_endpoint_formatter contact_status_formatter
ast_endpoint_state
Valid states for an endpoint.
Definition: endpoints.h:51
static void sip_options_notify_endpoint_state_compositors(struct sip_options_aor *aor_options, enum ast_sip_contact_status_type status)
Function which notifies endpoint state compositors of a state change of an AOR.
#define ast_verb(level,...)
Definition: logger.h:455
struct ast_sip_contact * contact
The contact we qualified.
const char * ast_sip_get_contact_short_status_label(const enum ast_sip_contact_status_type status)
int reload
Whether this is a reload or not.
struct ao2_container * existing
Optional container of existing AOR s.
AO2_STRING_FIELD_SORT_FN(ast_sip_contact_status, name)
Sort function for contact statuses.
int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
Add a header to an outbound SIP message.
Definition: res_pjsip.c:5063
static enum ast_endpoint_state sip_options_get_endpoint_state_compositor_state(const struct sip_options_endpoint_state_compositor *endpoint_state_compositor)
Return the current state of an endpoint state compositor.
static int sip_options_qualify_aor(void *obj)
Task to qualify contacts of an AOR.
int ast_sip_persistent_endpoint_update_state(const char *endpoint_name, enum ast_endpoint_state state)
Change state of a persistent endpoint.
ast_sip_contact_status_type
Status type for a contact.
Definition: res_pjsip.h:323
Structure which contains status information for an AOR feeding an endpoint state compositor.
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
enum ast_sip_contact_status_type status
The new status of the contact.
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 struct ao2_container * sip_options_contact_statuses_alloc(void)
Helper function to allocate a contact statuses container.
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.
Definition: res_pjsip.c:5448
Structure which contains information required to synchronize.
#define ao2_bump(obj)
Definition: astobj2.h:491
int ast_res_pjsip_init_options_handling(int reload)
static char * cli_show_qualify_aor(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
unsigned int qualify_frequency
Definition: res_pjsip.h:375
struct ast_sip_sched_task * ast_sip_schedule_task(struct ast_taskprocessor *serializer, int interval, ast_sip_task sip_task, const char *name, void *task_data, enum ast_sip_scheduler_task_flags flags)
Schedule a task to run in the res_pjsip thread pool.
void ast_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
Register an endpoint formatter.
Definition: res_pjsip.c:3679
#define EVENT_FLAG_SYSTEM
Definition: manager.h:71
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
static void sip_options_remove_contact_status(struct sip_options_aor *aor_options, struct ast_sip_contact *contact)
Remove contact status for a hint.
static char * cli_qualify(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int sip_contact_to_ami(const struct ast_sip_contact *contact, struct ast_str **buf)
#define CONTACT_STATUS_BUCKETS
These are the number of contact status buckets.
const ast_string_field endpoint_name
Definition: res_pjsip.h:303
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
A wrapper for contact that adds the aor_id and a consistent contact id. Used by ast_sip_for_each_cont...
Definition: res_pjsip.h:396
General Asterisk PBX channel definitions.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
static int sip_options_aor_observer_deleted_task(void *obj)
Task to delete an AOR from the known universe.
const int fd
Definition: cli.h:159
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
static int sip_options_set_contact_status_unqualified(void *obj, void *arg, int flags)
Transition the contact status to unqualified mode.
static int sip_options_contact_status_available_count(void *obj, void *arg, int flags)
Count AVAILABLE qualified contacts.
int ast_sip_push_task_wait_serializer(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to the serializer and wait for it to complete.
Definition: res_pjsip.c:5218
#define AST_MAX_EXTENSION
Definition: channel.h:135
static int sip_options_contact_status_notify_task(void *obj)
Task to notify an AOR of a contact status change.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:219
static int sip_options_synchronize_task(void *obj)
Task to synchronize our local container of AORs and endpoint state compositors with the current confi...
static struct ao2_container * endpoints
#define ao2_ref(o, delta)
Definition: astobj2.h:464
In case you didn&#39;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.
Definition: manager.c:1625
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.
Definition: res_pjsip.c:5420
#define ao2_lock(a)
Definition: astobj2.h:718
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
ao2 object sorter based on sorcery id.
Definition: sorcery.c:2435
static pjsip_module options_module
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
static struct ao2_container * sip_options_endpoint_state_compositors
struct mansession * s
Definition: res_pjsip.h:2739
static void endpoint_observer_deleted(const void *obj)
Observer callback invoked on endpoint deletion.
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
static void sip_options_contact_callback_data_dtor(void *obj)
Destructor for contact callback data.
struct ast_taskprocessor * ast_sip_create_serializer_group(const char *name, struct ast_serializer_shutdown_group *shutdown_group)
Create a new serializer for SIP tasks.
Definition: res_pjsip.c:5128
double qualify_timeout
Definition: res_pjsip.h:311
static struct ast_sip_contact_status * sip_contact_status_alloc(const char *name)
#define AST_VECTOR(name, type)
Define a vector structure.
Definition: vector.h:44
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
unsigned int ast_sip_get_max_initial_qualify_time(void)
Retrieve the system max initial qualify time.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4179
unsigned int ast_sip_get_send_contact_status_on_update_registration(void)
Retrieve the global setting &#39;send_contact_status_on_update_registration&#39;.
struct sip_options_endpoint_state_compositor * endpoint_state_compositor
The endpoint state compositor.
Task details for adding an AOR to an endpoint state compositor.
Core PBX routines and definitions.
struct sip_options_aor * aor_options
The AOR options for this AOR.
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.
Definition: sorcery.c:2386
enum ast_sip_contact_status_type status
Definition: res_pjsip.h:351
Structure which contains an AOR and contacts for qualifying purposes.
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:196
static int sip_options_aor_remove_task(void *obj)
Task which removes an AOR from all of the ESCs it is reporting to.
const char *const * argv
Definition: cli.h:161
struct ast_sip_contact * contact
Definition: res_pjsip.h:402
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
Structure used to contain information for an OPTIONS callback.
static struct ast_sip_contact_status * sip_contact_status_copy(const struct ast_sip_contact_status *src)
struct ast_sip_contact * contact
The contact itself.
struct timeval rtt_start
The time at which this OPTIONS attempt was started.
#define ENDPOINT_STATE_COMPOSITOR_BUCKETS
These are the number of buckets to store endpoint state compositors.
#define ast_string_fields_copy(copy, orig)
Copy all string fields from one instance to another of the same structure.
Definition: stringfields.h:627
#define LOG_ERROR
Definition: logger.h:285
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
struct ast_taskprocessor * serializer
The serializer for this AOR.
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
Copy all object references in the src container into the dest container.
#define CLI_SHOWUSAGE
Definition: cli.h:45
static int sip_options_aor_observer_modified_task(void *obj)
Task to synchronize the AOR.
static void sip_options_publish_contact_state(const struct sip_options_aor *aor_options, const struct ast_sip_contact_status *contact_status)
Function which publishes a contact status update to all interested endpoints.
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:5138
AO2_STRING_FIELD_CMP_FN(ast_sip_contact_status, name)
Comparator function for contact statuses.
int ast_sip_format_contact_ami(void *obj, void *arg, int flags)
Formats the contact and sends over AMI.
Interface for a sorcery object type observer.
Definition: sorcery.h:332
static int sip_options_synchronize_aor_task(void *obj)
Task to synchronize an AOR with our local state.
const char * ast_sip_get_contact_status_label(const enum ast_sip_contact_status_type status)
translate ast_sip_contact_status_type to character string.
int added
Whether this AOR is being added.
Contact associated with an address of record.
Definition: res_pjsip.h:281
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
Definition: res_pjsip.c:5133
static int sip_options_unused_endpoint_state_compositor(void *obj, void *arg, int flags)
Callback function used to unlink and remove event state compositors that have no AORs feeding them...
#define DEFAULT_LANGUAGE
Definition: pjsip_options.c:96
userdata associated with baseline taskprocessor test
static int format_contact_status_for_aor(void *obj, void *arg, int flags)
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
struct sip_options_aor * aor_options
The AOR options.
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define LOG_NOTICE
Definition: logger.h:263
static struct ast_taskprocessor * management_serializer
static int contact_status_publish_update_task(void *obj)
Task to notify endpoints of a contact status change.
#define ast_strlen_zero(a)
Definition: muted.c:73
struct ast_sip_contact_status * ast_sip_get_contact_status(const struct ast_sip_contact *contact)
Retrieve the current status for a contact.
#define CLI_FAILURE
Definition: cli.h:46
struct timeval expiration_time
Definition: res_pjsip.h:305
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:627
static int reload(void)
Definition: cdr_mysql.c:741
static void contact_observer_created(const void *obj)
Observer callback invoked on contact creation.
int(* format_ami)(const struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami)
Callback used to format endpoint information over AMI.
Definition: res_pjsip.h:2767
struct ao2_container * permanent_contacts
Definition: res_pjsip.h:383
struct ast_sip_aor * aor
The AOR which contains the new configuraton.
#define AST_STATSD_TIMER
Definition: statsd.h:41
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
An API for managing task processing threads that can be shared across modules.
static int sip_options_synchronize_endpoint(void *obj, void *arg, int flags)
Synchronize an endpoint with our local state.
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.
static int sip_options_synchronize_aor(void *obj, void *arg, int flags)
Synchronize an AOR with our local state.
char name[0]
The name of the AOR.
static int sip_options_unused_aor(void *obj, void *arg, int flags)
Callback which removes any unused AORs that remained after reloading.
const char * usage
Definition: cli.h:177
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.
Definition: sorcery.c:1897
static int sip_options_contact_update_task(void *obj)
Task which updates a dynamic contact to an AOR.
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
void ast_sip_persistent_endpoint_publish_contact_state(const char *endpoint_name, const struct ast_sip_contact_status *contact_status)
Publish the change of state for a contact.
#define EVENT_FLAG_REPORTING
Definition: manager.h:80
#define CLI_SUCCESS
Definition: cli.h:44
#define AST_STATSD_GAUGE
Support for publishing to a statsd server.
Definition: statsd.h:32
const ast_string_field aor
Definition: res_pjsip.h:303
static pj_bool_t options_on_rx_request(pjsip_rx_data *rdata)
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
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.
Definition: sorcery.c:2418
Replace objects with duplicate keys in container.
Definition: astobj2.h:1215
char * strsep(char **str, const char *delims)
char available
The last contributed available status of the named AOR (1 if available, 0 if not available) ...
A ast_taskprocessor structure is a singleton by name.
Definition: taskprocessor.c:69
#define DEFAULT_ENCODING
Definition: pjsip_options.c:97
char active
Non-zero if the compositor is in normal operation. i.e. Not being setup/reconfigured.
static int sip_options_cleanup_aor_task(void *obj)
Management task to clean up an AOR.
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...
Definition: astobj2.h:1841
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Standard Command Line Interface.
static int sip_options_determine_initial_qualify_time(int qualify_frequency)
Determine an initial time for scheduling AOR qualifying.
static void aor_observer_deleted(const void *obj)
Observer callback invoked on AOR deletion.
static int sip_options_contact_delete_task(void *obj)
Task which deletes a dynamic contact from an AOR.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
static int sip_options_endpoint_observer_modified_task(void *obj)
Task to synchronize the endpoint.
static struct ao2_container * sip_options_aors
int ast_sorcery_object_id_hash(const void *obj, int flags)
ao2 object hasher based on sorcery id.
Definition: sorcery.c:2470
struct ao2_container * contacts
All contacts associated with this AOR.
#define AOR_STATUS_BUCKETS
These are the number of buckets (per endpoint state compositor) to use to store AOR statuses...
static int sip_options_endpoint_compositor_remove_task(void *obj)
Task which adds removes an AOR from an endpoint state compositor.
int ast_sip_sorcery_object_to_ami(const void *obj, struct ast_str **buf)
Converts a sorcery object to a string of object properties.
int authenticate_qualify
Definition: res_pjsip.h:377
#define CONTACT_BUCKETS
These are the number of buckets (per AOR) to use to store contacts.
static void contact_observer_deleted(const void *obj)
Observer callback invoked on contact deletion.
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:78
#define ast_random_double()
Returns a random number between 0.0 and 1.0, inclusive.
Definition: utils.h:599
Reject objects with duplicate keys in container.
Definition: astobj2.h:1192
void ast_res_pjsip_cleanup_options_handling(void)
#define MAX_UNLOAD_TIMEOUT_TIME
Maximum wait time to join the below shutdown group.
Generic container type.
static int ami_show_contacts(struct mansession *s, const struct message *m)
static void aor_observer_modified(const void *obj)
Observer callback invoked on AOR creation or modification.
void ast_statsd_log_string_va(const char *metric_name, const char *metric_type, const char *value, double sample_rate,...)
Send a stat to the configured statsd server.
Definition: res_statsd.c:176
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 &#39;on_contact&#39; handler.
Definition: location.c:719
const ast_string_field aors
Definition: res_pjsip.h:821
static int sip_options_remove_contact(void *obj, void *arg, int flags)
Forward declaration of this helpful function.
static char * cli_reload_qualify_aor(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int sip_options_contact_add_task(void *obj)
Task which adds a dynamic contact to an AOR.
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:186
const ast_string_field uri
Definition: res_pjsip.h:303
static int format_ami_contactlist_handler(void *obj, void *arg, int flags)
#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered)
Remove an element from a vector by index.
Definition: vector.h:412
static void sip_options_contact_status_update(struct ast_sip_contact_status *contact_status)
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
static struct ast_serializer_shutdown_group * shutdown_group
Shutdown group for options serializers.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
struct ast_sip_sched_task * sched_task
The scheduler task for this AOR.
static int sip_options_qualify_contact(void *obj, void *arg, int flags)
Send a SIP OPTIONS request for a contact.
static int sip_options_contact_add_management_task(void *obj)
Task to add a dynamic contact to an AOR in its serializer.
const ast_string_field aor
Definition: res_pjsip.h:347
static int sip_options_endpoint_observer_deleted_task(void *obj)
Task to delete an endpoint from the known universe.
static const struct ast_sorcery_observer endpoint_observer_callbacks
Observer callbacks for endpoints.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
int ast_sip_send_out_of_dialog_request(pjsip_tx_data *tdata, struct ast_sip_endpoint *endpoint, int timeout, void *token, void(*callback)(void *token, pjsip_event *e))
General purpose method for sending an Out-Of-Dialog SIP request.
Definition: res_pjsip.c:4993
#define AOR_BUCKETS
These are the number of buckets to store AORs in.
static void sip_options_set_contact_status(struct ast_sip_contact_status *contact_status, enum ast_sip_contact_status_type status)
Set the contact status for a contact.
static struct ao2_container * get_all_contacts(void)
jack_status_t status
Definition: app_jack.c:146
static void sip_options_update_endpoint_state_compositor_aor(struct sip_options_endpoint_state_compositor *endpoint_state_compositor, const char *name, enum ast_sip_contact_status_type status)
Update the AOR status on an endpoint state compositor.
int ast_sip_create_request(const char *method, struct pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint, const char *uri, struct ast_sip_contact *contact, pjsip_tx_data **tdata)
General purpose method for creating a SIP request.
Definition: res_pjsip.c:4490
static char prefix[MAX_PREFIX]
Definition: http.c:141
Task details for adding an AOR to an endpoint state compositor.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3201
static struct test_val a
#define ao2_link(container, obj)
Definition: astobj2.h:1549
struct ao2_container * dynamic_contacts
Only dynamic contacts associated with this AOR.