res_pjsip_outbound_registration.c: Fix whitespace conflict potential.
[asterisk/asterisk.git] / res / res_pjsip_outbound_registration.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*** MODULEINFO
20         <depend>pjproject</depend>
21         <depend>res_pjsip</depend>
22         <support_level>core</support_level>
23  ***/
24
25 #include "asterisk.h"
26
27 #include <pjsip.h>
28 #include <pjsip_ua.h>
29
30 #include "asterisk/res_pjsip.h"
31 #include "asterisk/res_pjsip_cli.h"
32 #include "asterisk/module.h"
33 #include "asterisk/taskprocessor.h"
34 #include "asterisk/cli.h"
35 #include "asterisk/stasis_system.h"
36 #include "asterisk/threadstorage.h"
37 #include "res_pjsip/include/res_pjsip_private.h"
38
39 /*** DOCUMENTATION
40         <configInfo name="res_pjsip_outbound_registration" language="en_US">
41                 <synopsis>SIP resource for outbound registrations</synopsis>
42                 <description><para>
43                         <emphasis>Outbound Registration</emphasis>
44                         </para>
45                         <para>This module allows <literal>res_pjsip</literal> to register to other SIP servers.</para>
46                 </description>
47                 <configFile name="pjsip.conf">
48                         <configObject name="registration">
49                                 <synopsis>The configuration for outbound registration</synopsis>
50                                 <description><para>
51                                         Registration is <emphasis>COMPLETELY</emphasis> separate from the rest of
52                                         <literal>pjsip.conf</literal>. A minimal configuration consists of
53                                         setting a <literal>server_uri</literal> and a <literal>client_uri</literal>.
54                                 </para></description>
55                                 <configOption name="auth_rejection_permanent" default="yes">
56                                         <synopsis>Determines whether failed authentication challenges are treated
57                                         as permanent failures.</synopsis>
58                                         <description><para>If this option is enabled and an authentication challenge fails,
59                                         registration will not be attempted again until the configuration is reloaded.</para></description>
60                                 </configOption>
61                                 <configOption name="client_uri">
62                                         <synopsis>Client SIP URI used when attemping outbound registration</synopsis>
63                                         <description><para>
64                                                 This is the address-of-record for the outbound registration (i.e. the URI in
65                                                 the To header of the REGISTER).</para>
66                                                 <para>For registration with an ITSP, the client SIP URI may need to consist of
67                                                 an account name or number and the provider's hostname for their registrar, e.g.
68                                                 client_uri=1234567890@example.com. This may differ between providers.</para>
69                                                 <para>For registration to generic registrars, the client SIP URI will depend
70                                                 on networking specifics and configuration of the registrar.
71                                         </para></description>
72                                 </configOption>
73                                 <configOption name="contact_user">
74                                         <synopsis>Contact User to use in request</synopsis>
75                                 </configOption>
76                                 <configOption name="expiration" default="3600">
77                                         <synopsis>Expiration time for registrations in seconds</synopsis>
78                                 </configOption>
79                                 <configOption name="max_retries" default="10">
80                                         <synopsis>Maximum number of registration attempts.</synopsis>
81                                 </configOption>
82                                 <configOption name="outbound_auth" default="">
83                                         <synopsis>Authentication object to be used for outbound registrations.</synopsis>
84                                 </configOption>
85                                 <configOption name="outbound_proxy" default="">
86                                         <synopsis>Outbound Proxy used to send registrations</synopsis>
87                                 </configOption>
88                                 <configOption name="retry_interval" default="60">
89                                         <synopsis>Interval in seconds between retries if outbound registration is unsuccessful</synopsis>
90                                 </configOption>
91                                 <configOption name="forbidden_retry_interval" default="0">
92                                         <synopsis>Interval used when receiving a 403 Forbidden response.</synopsis>
93                                         <description><para>
94                                                 If a 403 Forbidden is received, chan_pjsip will wait
95                                                 <replaceable>forbidden_retry_interval</replaceable> seconds before
96                                                 attempting registration again. If 0 is specified, chan_pjsip will not
97                                                 retry after receiving a 403 Forbidden response. Setting this to a non-zero
98                                                 value goes against a "SHOULD NOT" in RFC3261, but can be used to work around
99                                                 buggy registrars.
100                                         </para></description>
101                                 </configOption>
102                                 <configOption name="server_uri">
103                                         <synopsis>SIP URI of the server to register against</synopsis>
104                                         <description><para>
105                                                 This is the URI at which to find the registrar to send the outbound REGISTER. This URI
106                                                 is used as the request URI of the outbound REGISTER request from Asterisk.</para>
107                                                 <para>For registration with an ITSP, the setting may often be just the domain of
108                                                 the registrar, e.g. sip:sip.example.com.
109                                         </para></description>
110                                 </configOption>
111                                 <configOption name="transport">
112                                         <synopsis>Transport used for outbound authentication</synopsis>
113                                         <description>
114                                                 <note><para>A <replaceable>transport</replaceable> configured in
115                                                 <literal>pjsip.conf</literal>. As with other <literal>res_pjsip</literal> modules, this will use the first available transport of the appropriate type if unconfigured.</para></note>
116                                         </description>
117                                 </configOption>
118                                 <configOption name="line">
119                                         <synopsis>Whether to add a 'line' parameter to the Contact for inbound call matching</synopsis>
120                                         <description><para>
121                                                 When enabled this option will cause a 'line' parameter to be added to the Contact
122                                                 header placed into the outgoing registration request. If the remote server sends a call
123                                                 this line parameter will be used to establish a relationship to the outbound registration,
124                                                 ultimately causing the configured endpoint to be used.
125                                         </para></description>
126                                 </configOption>
127                                 <configOption name="endpoint">
128                                         <synopsis>Endpoint to use for incoming related calls</synopsis>
129                                         <description><para>
130                                                 When line support is enabled this configured endpoint name is used for incoming calls
131                                                 that are related to the outbound registration.
132                                         </para></description>
133                                 </configOption>
134                                 <configOption name="type">
135                                         <synopsis>Must be of type 'registration'.</synopsis>
136                                 </configOption>
137                                 <configOption name="support_path">
138                                         <synopsis>Enables Path support for outbound REGISTER requests.</synopsis>
139                                         <description><para>
140                                                 When this option is enabled, outbound REGISTER requests will advertise
141                                                 support for Path headers so that intervening proxies can add to the Path
142                                                 header as necessary.
143                                         </para></description>
144                                 </configOption>
145                         </configObject>
146                 </configFile>
147         </configInfo>
148         <manager name="PJSIPUnregister" language="en_US">
149                 <synopsis>
150                         Unregister an outbound registration.
151                 </synopsis>
152                 <syntax>
153                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
154                         <parameter name="Registration" required="true">
155                                 <para>The outbound registration to unregister.</para>
156                         </parameter>
157                 </syntax>
158                 <description>
159                         <para>
160                         Unregisters the specified outbound registration and stops future registration attempts.
161                         Call PJSIPRegister to start registration and schedule re-registrations according to configuration.
162             </para>
163                 </description>
164         </manager>
165         <manager name="PJSIPRegister" language="en_US">
166                 <synopsis>
167                         Register an outbound registration.
168                 </synopsis>
169                 <syntax>
170                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
171                         <parameter name="Registration" required="true">
172                                 <para>The outbound registration to register.</para>
173                         </parameter>
174                 </syntax>
175                 <description>
176                         <para>
177                         Unregisters the specified outbound registration then starts registration and schedules re-registrations
178                         according to configuration.
179                         future registrations.
180             </para>
181                 </description>
182         </manager>
183         <manager name="PJSIPShowRegistrationsOutbound" language="en_US">
184                 <synopsis>
185                         Lists PJSIP outbound registrations.
186                 </synopsis>
187                 <syntax />
188                 <description>
189                         <para>
190                         In response <literal>OutboundRegistrationDetail</literal> events showing configuration and status
191                         information are raised for each outbound registration object. <literal>AuthDetail</literal>
192                         events are raised for each associated auth object as well.  Once all events are completed an
193                         <literal>OutboundRegistrationDetailComplete</literal> is issued.
194                         </para>
195                 </description>
196         </manager>
197  ***/
198
199 /*! \brief Some thread local storage used to determine if the running thread invoked the callback */
200 AST_THREADSTORAGE(register_callback_invoked);
201
202 /*! \brief Amount of buffer time (in seconds) before expiration that we re-register at */
203 #define REREGISTER_BUFFER_TIME 10
204
205 /*! \brief Size of the buffer for creating a unique string for the line */
206 #define LINE_PARAMETER_SIZE 8
207
208 /*! \brief Various states that an outbound registration may be in */
209 enum sip_outbound_registration_status {
210         /*! \brief Currently unregistered */
211         SIP_REGISTRATION_UNREGISTERED = 0,
212         /*! \brief Registered, yay! */
213         SIP_REGISTRATION_REGISTERED,
214         /*! \brief Registration was rejected, but response was temporal */
215         SIP_REGISTRATION_REJECTED_TEMPORARY,
216         /*! \brief Registration was rejected, permanently */
217         SIP_REGISTRATION_REJECTED_PERMANENT,
218         /*! \brief Registration has been stopped */
219         SIP_REGISTRATION_STOPPED,
220 };
221
222 static const char *sip_outbound_registration_status_str[] = {
223         [SIP_REGISTRATION_UNREGISTERED] = "Unregistered",
224         [SIP_REGISTRATION_REGISTERED] = "Registered",
225         [SIP_REGISTRATION_REJECTED_TEMPORARY] = "Rejected",
226         [SIP_REGISTRATION_REJECTED_PERMANENT] = "Rejected",
227         [SIP_REGISTRATION_STOPPED] = "Stopped",
228 };
229
230 /*! \brief Outbound registration information */
231 struct sip_outbound_registration {
232         /*! \brief Sorcery object details */
233         SORCERY_OBJECT(details);
234         /*! \brief Stringfields */
235         AST_DECLARE_STRING_FIELDS(
236                 /*! \brief URI for the registrar */
237                 AST_STRING_FIELD(server_uri);
238                 /*! \brief URI for the AOR */
239                 AST_STRING_FIELD(client_uri);
240                 /*! \brief Optional user for contact header */
241                 AST_STRING_FIELD(contact_user);
242                 /*! \brief Explicit transport to use for registration */
243                 AST_STRING_FIELD(transport);
244                 /*! \brief Outbound proxy to use */
245                 AST_STRING_FIELD(outbound_proxy);
246                 /*! \brief Endpoint to use for related incoming calls */
247                 AST_STRING_FIELD(endpoint);
248         );
249         /*! \brief Requested expiration time */
250         unsigned int expiration;
251         /*! \brief Interval at which retries should occur for temporal responses */
252         unsigned int retry_interval;
253         /*! \brief Interval at which retries should occur for permanent responses */
254         unsigned int forbidden_retry_interval;
255         /*! \brief Treat authentication challenges that we cannot handle as permanent failures */
256         unsigned int auth_rejection_permanent;
257         /*! \brief Maximum number of retries permitted */
258         unsigned int max_retries;
259         /*! \brief Whether to add a line parameter to the outbound Contact or not */
260         unsigned int line;
261         /*! \brief Configured authentication credentials */
262         struct ast_sip_auth_vector outbound_auths;
263         /*! \brief Whether Path support is enabled */
264         unsigned int support_path;
265 };
266
267 /*! \brief Outbound registration client state information (persists for lifetime of regc) */
268 struct sip_outbound_registration_client_state {
269         /*! \brief Current status of this registration */
270         enum sip_outbound_registration_status status;
271         /*! \brief Outbound registration client */
272         pjsip_regc *client;
273         /*! \brief Timer entry for retrying on temporal responses */
274         pj_timer_entry timer;
275         /*! \brief Optional line parameter placed into Contact */
276         char line[LINE_PARAMETER_SIZE];
277         /*! \brief Current number of retries */
278         unsigned int retries;
279         /*! \brief Maximum number of retries permitted */
280         unsigned int max_retries;
281         /*! \brief Interval at which retries should occur for temporal responses */
282         unsigned int retry_interval;
283         /*! \brief Interval at which retries should occur for permanent responses */
284         unsigned int forbidden_retry_interval;
285         /*! \brief Treat authentication challenges that we cannot handle as permanent failures */
286         unsigned int auth_rejection_permanent;
287         /*! \brief Determines whether SIP Path support should be advertised */
288         unsigned int support_path;
289         /*! \brief Serializer for stuff and things */
290         struct ast_taskprocessor *serializer;
291         /*! \brief Configured authentication credentials */
292         struct ast_sip_auth_vector outbound_auths;
293         /*! \brief Registration should be destroyed after completion of transaction */
294         unsigned int destroy:1;
295         /*! \brief Non-zero if we have attempted sending a REGISTER with authentication */
296         unsigned int auth_attempted:1;
297 };
298
299 /*! \brief Outbound registration state information (persists for lifetime that registration should exist) */
300 struct sip_outbound_registration_state {
301         /*! \brief Outbound registration configuration object */
302         struct sip_outbound_registration *registration;
303         /*! \brief Client state information */
304         struct sip_outbound_registration_client_state *client_state;
305 };
306
307 /*! \brief Default number of state container buckets */
308 #define DEFAULT_STATE_BUCKETS 53
309 static AO2_GLOBAL_OBJ_STATIC(current_states);
310
311 /*! \brief hashing function for state objects */
312 static int registration_state_hash(const void *obj, const int flags)
313 {
314         const struct sip_outbound_registration_state *object;
315         const char *key;
316
317         switch (flags & OBJ_SEARCH_MASK) {
318         case OBJ_SEARCH_KEY:
319                 key = obj;
320                 break;
321         case OBJ_SEARCH_OBJECT:
322                 object = obj;
323                 key = ast_sorcery_object_get_id(object->registration);
324                 break;
325         default:
326                 ast_assert(0);
327                 return 0;
328         }
329         return ast_str_hash(key);
330 }
331
332 /*! \brief comparator function for state objects */
333 static int registration_state_cmp(void *obj, void *arg, int flags)
334 {
335         const struct sip_outbound_registration_state *object_left = obj;
336         const struct sip_outbound_registration_state *object_right = arg;
337         const char *right_key = arg;
338         int cmp;
339
340         switch (flags & OBJ_SEARCH_MASK) {
341         case OBJ_SEARCH_OBJECT:
342                 right_key = ast_sorcery_object_get_id(object_right->registration);
343                 /* Fall through */
344         case OBJ_SEARCH_KEY:
345                 cmp = strcmp(ast_sorcery_object_get_id(object_left->registration), right_key);
346                 break;
347         case OBJ_SEARCH_PARTIAL_KEY:
348                 /* Not supported by container. */
349                 ast_assert(0);
350                 return 0;
351         default:
352                 cmp = 0;
353                 break;
354         }
355         if (cmp) {
356                 return 0;
357         }
358         return CMP_MATCH;
359 }
360
361 static struct sip_outbound_registration_state *get_state(const char *id)
362 {
363         RAII_VAR(struct ao2_container *, states,
364                  ao2_global_obj_ref(current_states), ao2_cleanup);
365         return states ? ao2_find(states, id, OBJ_SEARCH_KEY) : NULL;
366 }
367
368 static struct ao2_container *get_registrations(void)
369 {
370         struct ao2_container *registrations = ast_sorcery_retrieve_by_fields(
371                 ast_sip_get_sorcery(), "registration",
372                 AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
373
374         return registrations;
375 }
376
377 /*! \brief Callback function for matching an outbound registration based on line */
378 static int line_identify_relationship(void *obj, void *arg, int flags)
379 {
380         struct sip_outbound_registration_state *state = obj;
381         pjsip_param *line = arg;
382
383         return !pj_strcmp2(&line->value, state->client_state->line) ? CMP_MATCH | CMP_STOP : 0;
384 }
385
386 static struct pjsip_param *get_uri_option_line(const void *uri)
387 {
388         pjsip_sip_uri *pjuri;
389         static const pj_str_t LINE_STR = { "line", 4 };
390
391         if (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri)) {
392                 return NULL;
393         }
394         pjuri = pjsip_uri_get_uri(uri);
395         return pjsip_param_find(&pjuri->other_param, &LINE_STR);
396 }
397
398 /*! \brief Endpoint identifier which uses the 'line' parameter to establish a relationship to an outgoing registration */
399 static struct ast_sip_endpoint *line_identify(pjsip_rx_data *rdata)
400 {
401         pjsip_param *line;
402         RAII_VAR(struct ao2_container *, states, NULL, ao2_cleanup);
403         RAII_VAR(struct sip_outbound_registration_state *, state, NULL, ao2_cleanup);
404
405         if (!(line = get_uri_option_line(rdata->msg_info.to->uri))
406                 && !(line = get_uri_option_line(rdata->msg_info.msg->line.req.uri))) {
407                 return NULL;
408         }
409
410         states = ao2_global_obj_ref(current_states);
411         if (!states) {
412                 return NULL;
413         }
414
415         state = ao2_callback(states, 0, line_identify_relationship, line);
416         if (!state || ast_strlen_zero(state->registration->endpoint)) {
417                 return NULL;
418         }
419
420         ast_debug(3, "Determined relationship to outbound registration '%s' based on line '%s', using configured endpoint '%s'\n",
421                 ast_sorcery_object_get_id(state->registration), state->client_state->line, state->registration->endpoint);
422
423         return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", state->registration->endpoint);
424 }
425
426 static struct ast_sip_endpoint_identifier line_identifier = {
427         .identify_endpoint = line_identify,
428 };
429
430 /*! \brief Helper function which cancels the timer on a client */
431 static void cancel_registration(struct sip_outbound_registration_client_state *client_state)
432 {
433         if (pj_timer_heap_cancel(pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()), &client_state->timer)) {
434                 /* The timer was successfully cancelled, drop the refcount of client_state */
435                 ao2_ref(client_state, -1);
436         }
437 }
438
439 static pj_str_t PATH_NAME = { "path", 4 };
440
441 /*! \brief Helper function which sends a message and cleans up, if needed, on failure */
442 static pj_status_t registration_client_send(struct sip_outbound_registration_client_state *client_state,
443         pjsip_tx_data *tdata)
444 {
445         pj_status_t status;
446         int *callback_invoked;
447
448         callback_invoked = ast_threadstorage_get(&register_callback_invoked, sizeof(int));
449         if (!callback_invoked) {
450                 return PJ_ENOMEM;
451         }
452         *callback_invoked = 0;
453
454         /* Due to the message going out the callback may now be invoked, so bump the count */
455         ao2_ref(client_state, +1);
456         status = pjsip_regc_send(client_state->client, tdata);
457
458         /* If the attempt to send the message failed and the callback was not invoked we need to
459          * drop the reference we just added
460          */
461         if ((status != PJ_SUCCESS) && !(*callback_invoked)) {
462                 ao2_ref(client_state, -1);
463         }
464
465         return status;
466 }
467
468 /*! \brief Callback function for registering */
469 static int handle_client_registration(void *data)
470 {
471         RAII_VAR(struct sip_outbound_registration_client_state *, client_state, data, ao2_cleanup);
472         pjsip_tx_data *tdata;
473         pjsip_regc_info info;
474         char server_uri[PJSIP_MAX_URL_SIZE], client_uri[PJSIP_MAX_URL_SIZE];
475
476         if ((client_state->status == SIP_REGISTRATION_STOPPED) ||
477                 (pjsip_regc_register(client_state->client, PJ_FALSE, &tdata) != PJ_SUCCESS)) {
478                 return 0;
479         }
480
481         pjsip_regc_get_info(client_state->client, &info);
482         ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
483         ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
484         ast_debug(3, "REGISTER attempt %u to '%s' with client '%s'\n",
485                   client_state->retries + 1, server_uri, client_uri);
486
487         if (client_state->support_path) {
488                 pjsip_supported_hdr *hdr;
489
490                 hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_SUPPORTED, NULL);
491                 if (!hdr) {
492                         /* insert a new Supported header */
493                         hdr = pjsip_supported_hdr_create(tdata->pool);
494                         if (!hdr) {
495                                 return -1;
496                         }
497
498                         pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
499                 }
500
501                 /* add on to the existing Supported header */
502                 pj_strassign(&hdr->values[hdr->count++], &PATH_NAME);
503         }
504
505         registration_client_send(client_state, tdata);
506
507         return 0;
508 }
509
510 /*! \brief Timer callback function, used just for registrations */
511 static void sip_outbound_registration_timer_cb(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
512 {
513         struct sip_outbound_registration_client_state *client_state = entry->user_data;
514         pjsip_regc_info info;
515
516         pjsip_regc_get_info(client_state->client, &info);
517         ast_debug(1, "Attempting scheduled outbound registration attempt to server '%.*s' from client '%.*s'\n",
518                         (int) info.server_uri.slen, info.server_uri.ptr,
519                         (int) info.client_uri.slen, info.client_uri.ptr);
520
521         ao2_ref(client_state, +1);
522         if (ast_sip_push_task(client_state->serializer, handle_client_registration, client_state)) {
523                 ast_log(LOG_WARNING, "Scheduled outbound registration to server '%.*s' from client '%.*s' could not be executed\n",
524                                 (int) info.server_uri.slen, info.server_uri.ptr,
525                                 (int) info.client_uri.slen, info.client_uri.ptr);
526                 ao2_ref(client_state, -1);
527         }
528         ao2_ref(client_state, -1);
529
530         entry->id = 0;
531 }
532
533 /*! \brief Helper function which sets up the timer to re-register in a specific amount of time */
534 static void schedule_registration(struct sip_outbound_registration_client_state *client_state, unsigned int seconds)
535 {
536         pj_time_val delay = { .sec = seconds, };
537         pjsip_regc_info info;
538
539         cancel_registration(client_state);
540
541         pjsip_regc_get_info(client_state->client, &info);
542         ast_debug(1, "Scheduling outbound registration to server '%.*s' from client '%.*s' in %d seconds\n",
543                         (int) info.server_uri.slen, info.server_uri.ptr,
544                         (int) info.client_uri.slen, info.client_uri.ptr,
545                         seconds);
546
547         ao2_ref(client_state, +1);
548         if (pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(), &client_state->timer, &delay) != PJ_SUCCESS) {
549                 ast_log(LOG_WARNING, "Failed to schedule registration to server '%.*s' from client '%.*s'\n",
550                                 (int) info.server_uri.slen, info.server_uri.ptr,
551                                 (int) info.client_uri.slen, info.client_uri.ptr);
552                 ao2_ref(client_state, -1);
553         }
554 }
555
556 /*! \brief Callback function for unregistering (potentially) and destroying state */
557 static int handle_client_state_destruction(void *data)
558 {
559         RAII_VAR(struct sip_outbound_registration_client_state *, client_state, data, ao2_cleanup);
560
561         cancel_registration(client_state);
562
563         if (client_state->client) {
564                 pjsip_regc_info info;
565
566                 pjsip_regc_get_info(client_state->client, &info);
567
568                 if (info.is_busy == PJ_TRUE) {
569                         /* If a client transaction is in progress we defer until it is complete */
570                         client_state->destroy = 1;
571                         return 0;
572                 }
573
574                 if (client_state->status != SIP_REGISTRATION_UNREGISTERED && client_state->status != SIP_REGISTRATION_REJECTED_PERMANENT) {
575                         pjsip_tx_data *tdata;
576
577                         if (pjsip_regc_unregister(client_state->client, &tdata) == PJ_SUCCESS) {
578                                 pjsip_regc_send(client_state->client, tdata);
579                         }
580                 }
581
582                 pjsip_regc_destroy(client_state->client);
583         }
584
585         client_state->status = SIP_REGISTRATION_STOPPED;
586         ast_sip_auth_vector_destroy(&client_state->outbound_auths);
587
588         return 0;
589 }
590
591 /*! \brief Structure for registration response */
592 struct registration_response {
593         /*! \brief Response code for the registration attempt */
594         int code;
595         /*! \brief Expiration time for registration */
596         int expiration;
597         /*! \brief Retry-After value */
598         int retry_after;
599         /*! \brief Outbound registration client state */
600         struct sip_outbound_registration_client_state *client_state;
601         /*! \brief The response message */
602         pjsip_rx_data *rdata;
603         /*! \brief Request for which the response was received */
604         pjsip_tx_data *old_request;
605 };
606
607 /*! \brief Registration response structure destructor */
608 static void registration_response_destroy(void *obj)
609 {
610         struct registration_response *response = obj;
611
612         if (response->rdata) {
613                 pjsip_rx_data_free_cloned(response->rdata);
614         }
615
616         if (response->old_request) {
617                 pjsip_tx_data_dec_ref(response->old_request);
618         }
619
620         ao2_cleanup(response->client_state);
621 }
622
623 /* \brief Helper funtion which determines if a response code is temporal or not */
624 static int sip_outbound_registration_is_temporal(unsigned int code,
625                 struct sip_outbound_registration_client_state *client_state)
626 {
627         /* Shamelessly taken from pjsua */
628         if (code == PJSIP_SC_REQUEST_TIMEOUT ||
629                 code == PJSIP_SC_INTERNAL_SERVER_ERROR ||
630                 code == PJSIP_SC_BAD_GATEWAY ||
631                 code == PJSIP_SC_SERVICE_UNAVAILABLE ||
632                 code == PJSIP_SC_SERVER_TIMEOUT ||
633                 ((code == PJSIP_SC_UNAUTHORIZED ||
634                   code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED) &&
635                  !client_state->auth_rejection_permanent) ||
636                 PJSIP_IS_STATUS_IN_CLASS(code, 600)) {
637                 return 1;
638         } else {
639                 return 0;
640         }
641 }
642
643 static void schedule_retry(struct registration_response *response, unsigned int interval,
644                            const char *server_uri, const char *client_uri)
645 {
646         response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY;
647         schedule_registration(response->client_state, interval);
648
649         if (response->rdata) {
650                 ast_log(LOG_WARNING, "Temporal response '%d' received from '%s' on "
651                         "registration attempt to '%s', retrying in '%u'\n",
652                         response->code, server_uri, client_uri, interval);
653         } else {
654                 ast_log(LOG_WARNING, "No response received from '%s' on "
655                         "registration attempt to '%s', retrying in '%u'\n",
656                         server_uri, client_uri, interval);
657         }
658 }
659
660 /*! \brief Callback function for handling a response to a registration attempt */
661 static int handle_registration_response(void *data)
662 {
663         RAII_VAR(struct registration_response *, response, data, ao2_cleanup);
664         pjsip_regc_info info;
665         char server_uri[PJSIP_MAX_URL_SIZE], client_uri[PJSIP_MAX_URL_SIZE];
666
667         pjsip_regc_get_info(response->client_state->client, &info);
668         ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
669         ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
670
671         if (response->client_state->status == SIP_REGISTRATION_STOPPED) {
672                 ast_debug(1, "Not handling registration response from server '%s' for client '%s'. Registration already stopped\n",
673                                 server_uri, client_uri);
674                 return 0;
675         }
676
677         ast_debug(1, "Processing REGISTER response %d from server '%s' for client '%s'\n",
678                         response->code, server_uri, client_uri);
679
680         if (!response->client_state->auth_attempted &&
681                         (response->code == 401 || response->code == 407)) {
682                 pjsip_tx_data *tdata;
683                 if (!ast_sip_create_request_with_auth(&response->client_state->outbound_auths,
684                                 response->rdata, response->old_request, &tdata)) {
685                         response->client_state->auth_attempted = 1;
686                         ast_debug(1, "Sending authenticated REGISTER to server '%s' from client '%s'\n",
687                                         server_uri, client_uri);
688                         if (registration_client_send(response->client_state, tdata) != PJ_SUCCESS) {
689                                 response->client_state->auth_attempted = 0;
690                         }
691                         return 0;
692                 } else {
693                         ast_log(LOG_WARNING, "Failed to create authenticated REGISTER request to server '%s' from client '%s'\n",
694                                         server_uri, client_uri);
695                 }
696                 /* Otherwise, fall through so the failure is processed appropriately */
697         }
698
699         response->client_state->auth_attempted = 0;
700
701         if (PJSIP_IS_STATUS_IN_CLASS(response->code, 200)) {
702                 /* Check if this is in regards to registering or unregistering */
703                 if (response->expiration) {
704                         /* If the registration went fine simply reschedule registration for the future */
705                         ast_debug(1, "Outbound registration to '%s' with client '%s' successful\n", server_uri, client_uri);
706                         response->client_state->status = SIP_REGISTRATION_REGISTERED;
707                         response->client_state->retries = 0;
708                         schedule_registration(response->client_state, response->expiration - REREGISTER_BUFFER_TIME);
709                 } else {
710                         ast_debug(1, "Outbound unregistration to '%s' with client '%s' successful\n", server_uri, client_uri);
711                         response->client_state->status = SIP_REGISTRATION_UNREGISTERED;
712                 }
713         } else if (response->retry_after) {
714                 /* If we have been instructed to retry after a period of time, schedule it as such */
715                 schedule_retry(response, response->retry_after, server_uri, client_uri);
716         } else if (response->client_state->retry_interval && sip_outbound_registration_is_temporal(response->code, response->client_state)) {
717                 if (response->client_state->retries == response->client_state->max_retries) {
718                         /* If we received enough temporal responses to exceed our maximum give up permanently */
719                         response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT;
720                         ast_log(LOG_WARNING, "Maximum retries reached when attempting outbound registration to '%s' with client '%s', stopping registration attempt\n",
721                                 server_uri, client_uri);
722                 } else {
723                         /* On the other hand if we can still try some more do so */
724                         response->client_state->retries++;
725                         schedule_retry(response, response->client_state->retry_interval, server_uri, client_uri);
726                 }
727         } else {
728                 if (response->code == 403
729                         && response->client_state->forbidden_retry_interval
730                         && response->client_state->retries < response->client_state->max_retries) {
731                         /* A forbidden response retry interval is configured and there are retries remaining */
732                         response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY;
733                         response->client_state->retries++;
734                         schedule_registration(response->client_state, response->client_state->forbidden_retry_interval);
735                         ast_log(LOG_WARNING, "403 Forbidden fatal response received from '%s' on registration attempt to '%s', retrying in '%u' seconds\n",
736                                 server_uri, client_uri, response->client_state->forbidden_retry_interval);
737                 } else {
738                         /* Finally if there's no hope of registering give up */
739                         response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT;
740                         if (response->rdata) {
741                                 ast_log(LOG_WARNING, "Fatal response '%d' received from '%s' on registration attempt to '%s', stopping outbound registration\n",
742                                         response->code, server_uri, client_uri);
743                         } else {
744                                 ast_log(LOG_WARNING, "Fatal registration attempt to '%s', stopping outbound registration\n", client_uri);
745                         }
746                 }
747         }
748
749         ast_system_publish_registry("PJSIP", client_uri, server_uri, sip_outbound_registration_status_str[response->client_state->status], NULL);
750
751         /* If deferred destruction is in use see if we need to destroy now */
752         if (response->client_state->destroy) {
753                 handle_client_state_destruction(response->client_state);
754         }
755
756         return 0;
757 }
758
759 /*! \brief Callback function for outbound registration client */
760 static void sip_outbound_registration_response_cb(struct pjsip_regc_cbparam *param)
761 {
762         RAII_VAR(struct sip_outbound_registration_client_state *, client_state, param->token, ao2_cleanup);
763         struct registration_response *response;
764         pjsip_regc_info info;
765         int *callback_invoked;
766
767         callback_invoked = ast_threadstorage_get(&register_callback_invoked, sizeof(int));
768
769         ast_assert(callback_invoked != NULL);
770         ast_assert(client_state != NULL);
771
772         *callback_invoked = 1;
773
774         response = ao2_alloc(sizeof(*response), registration_response_destroy);
775         if (!response) {
776                 return;
777         }
778         response->code = param->code;
779         response->expiration = param->expiration;
780         response->client_state = client_state;
781         ao2_ref(response->client_state, +1);
782
783         pjsip_regc_get_info(client_state->client, &info);
784         ast_debug(1, "Received REGISTER response %d(%.*s) from server '%.*s' for client '%.*s\n",
785                         param->code, (int) param->reason.slen, param->reason.ptr,
786                         (int) info.server_uri.slen, info.server_uri.ptr,
787                         (int) info.client_uri.slen, info.client_uri.ptr);
788
789         if (param->rdata) {
790                 struct pjsip_retry_after_hdr *retry_after = pjsip_msg_find_hdr(param->rdata->msg_info.msg, PJSIP_H_RETRY_AFTER, NULL);
791                 pjsip_transaction *tsx;
792
793                 response->retry_after = retry_after ? retry_after->ivalue : 0;
794                 tsx = pjsip_rdata_get_tsx(param->rdata);
795                 response->old_request = tsx->last_tx;
796                 pjsip_tx_data_add_ref(response->old_request);
797                 pjsip_rx_data_clone(param->rdata, 0, &response->rdata);
798         }
799
800         if (ast_sip_push_task(client_state->serializer, handle_registration_response, response)) {
801                 ast_log(LOG_WARNING, "Failed to pass incoming registration response to threadpool\n");
802                 ao2_cleanup(response);
803         }
804 }
805
806 /*! \brief Destructor function for registration state */
807 static void sip_outbound_registration_state_destroy(void *obj)
808 {
809         struct sip_outbound_registration_state *state = obj;
810
811         ast_debug(3, "Destroying registration state for registration to server '%s' from client '%s'\n",
812                         state->registration->server_uri, state->registration->client_uri);
813
814         ao2_cleanup(state->registration);
815
816         if (!state->client_state) {
817                 /* Nothing to do */
818         } else if (!state->client_state->serializer) {
819                 ao2_ref(state->client_state, -1);
820         } else if (ast_sip_push_task(state->client_state->serializer,
821                 handle_client_state_destruction, state->client_state)) {
822                 ast_log(LOG_WARNING, "Failed to pass outbound registration client destruction to threadpool\n");
823                 ao2_ref(state->client_state, -1);
824         }
825 }
826
827 /*! \brief Destructor function for client registration state */
828 static void sip_outbound_registration_client_state_destroy(void *obj)
829 {
830         struct sip_outbound_registration_client_state *client_state = obj;
831
832         ast_taskprocessor_unreference(client_state->serializer);
833 }
834
835 /*! \brief Allocator function for registration state */
836 static struct sip_outbound_registration_state *sip_outbound_registration_state_alloc(struct sip_outbound_registration *registration)
837 {
838         struct sip_outbound_registration_state *state;
839
840         state = ao2_alloc(sizeof(*state), sip_outbound_registration_state_destroy);
841         if (!state) {
842                 return NULL;
843         }
844         state->client_state = ao2_alloc(sizeof(*state->client_state),
845                 sip_outbound_registration_client_state_destroy);
846         if (!state->client_state) {
847                 ao2_cleanup(state);
848                 return NULL;
849         }
850
851         state->client_state->serializer = ast_sip_create_serializer();
852         if (!state->client_state->serializer) {
853                 ao2_cleanup(state);
854                 return NULL;
855         }
856         state->client_state->status = SIP_REGISTRATION_UNREGISTERED;
857         state->client_state->timer.user_data = state->client_state;
858         state->client_state->timer.cb = sip_outbound_registration_timer_cb;
859
860         state->registration = ao2_bump(registration);
861         return state;
862 }
863
864 /*! \brief Destructor function for registration information */
865 static void sip_outbound_registration_destroy(void *obj)
866 {
867         struct sip_outbound_registration *registration = obj;
868
869         ast_sip_auth_vector_destroy(&registration->outbound_auths);
870
871         ast_string_field_free_memory(registration);
872 }
873
874 /*! \brief Allocator function for registration information */
875 static void *sip_outbound_registration_alloc(const char *name)
876 {
877         struct sip_outbound_registration *registration = ast_sorcery_generic_alloc(sizeof(*registration), sip_outbound_registration_destroy);
878         if (!registration || ast_string_field_init(registration, 256)) {
879                 ao2_cleanup(registration);
880                 return NULL;
881         }
882
883         return registration;
884 }
885
886 /*! \brief Helper function which populates a pj_str_t with a contact header */
887 static int sip_dialog_create_contact(pj_pool_t *pool, pj_str_t *contact, const char *user, const pj_str_t *target, pjsip_tpselector *selector,
888         const char *line)
889 {
890         pj_str_t tmp, local_addr;
891         pjsip_uri *uri;
892         pjsip_sip_uri *sip_uri;
893         pjsip_transport_type_e type = PJSIP_TRANSPORT_UNSPECIFIED;
894         int local_port;
895
896         pj_strdup_with_null(pool, &tmp, target);
897
898         if (!(uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0)) ||
899             (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
900                 return -1;
901         }
902
903         sip_uri = pjsip_uri_get_uri(uri);
904
905         if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
906                 type = PJSIP_TRANSPORT_TLS;
907         } else if (!sip_uri->transport_param.slen) {
908                 type = PJSIP_TRANSPORT_UDP;
909         } else {
910                 type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
911         }
912
913         if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
914                 return -1;
915         }
916
917         if (pj_strchr(&sip_uri->host, ':')) {
918                 type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
919         }
920
921         if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), pool, type, selector,
922                                                               &local_addr, &local_port) != PJ_SUCCESS) {
923                 return -1;
924         }
925
926         if (!pj_strchr(&sip_uri->host, ':') && pj_strchr(&local_addr, ':')) {
927                 type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
928         }
929
930         contact->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
931         contact->slen = pj_ansi_snprintf(contact->ptr, PJSIP_MAX_URL_SIZE,
932                                       "<%s:%s@%s%.*s%s:%d%s%s%s%s>",
933                                       (pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE) ? "sips" : "sip",
934                                       user,
935                                       (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
936                                       (int)local_addr.slen,
937                                       local_addr.ptr,
938                                       (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
939                                       local_port,
940                                       (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
941                                       (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "",
942                                       !ast_strlen_zero(line) ? ";line=" : "",
943                                       S_OR(line, ""));
944
945         return 0;
946 }
947
948 /*!
949  * \internal
950  * \brief Check if a registration can be reused
951  *
952  * This checks if the existing outbound registration's configuration differs from a newly-applied
953  * outbound registration to see if the applied one.
954  *
955  * \param existing The pre-existing outbound registration
956  * \param applied The newly-created registration
957  */
958 static int can_reuse_registration(struct sip_outbound_registration *existing,
959         struct sip_outbound_registration *applied)
960 {
961         int rc = 1;
962         struct ast_sorcery *sorcery = ast_sip_get_sorcery();
963         struct ast_variable *ve = ast_sorcery_objectset_create(sorcery, existing);
964         struct ast_variable *va = ast_sorcery_objectset_create(sorcery, applied);
965         struct ast_variable *vc = NULL;
966
967         if (ast_sorcery_changeset_create(ve, va, &vc) || vc != NULL) {
968                 rc = 0;
969                 ast_debug(4, "Registration '%s' changed.  Can't re-use.\n", ast_sorcery_object_get_id(existing));
970         } else {
971                 ast_debug(4, "Registration '%s' didn't change.  Can re-use\n", ast_sorcery_object_get_id(existing));
972         }
973
974         ast_variables_destroy(ve);
975         ast_variables_destroy(va);
976         ast_variables_destroy(vc);
977
978         return rc;
979 }
980
981 /*! \brief Helper function that allocates a pjsip registration client and configures it */
982 static int sip_outbound_registration_regc_alloc(void *data)
983 {
984         struct sip_outbound_registration_state *state = data;
985         RAII_VAR(struct sip_outbound_registration *, registration,
986                  ao2_bump(state->registration), ao2_cleanup);
987         pj_pool_t *pool;
988         pj_str_t tmp;
989         pjsip_uri *uri;
990         pj_str_t server_uri, client_uri, contact_uri;
991         pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
992
993         pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "URI Validation", 256, 256);
994         if (!pool) {
995                 ast_log(LOG_ERROR, "Could not create pool for URI validation on outbound registration '%s'\n",
996                         ast_sorcery_object_get_id(registration));
997                 return -1;
998         }
999
1000         pj_strdup2_with_null(pool, &tmp, registration->server_uri);
1001         uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0);
1002         if (!uri) {
1003                 ast_log(LOG_ERROR, "Invalid server URI '%s' specified on outbound registration '%s'\n",
1004                         registration->server_uri, ast_sorcery_object_get_id(registration));
1005                 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1006                 return -1;
1007         }
1008
1009         pj_strdup2_with_null(pool, &tmp, registration->client_uri);
1010         uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0);
1011         if (!uri) {
1012                 ast_log(LOG_ERROR, "Invalid client URI '%s' specified on outbound registration '%s'\n",
1013                         registration->client_uri, ast_sorcery_object_get_id(registration));
1014                 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1015                 return -1;
1016         }
1017
1018         pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1019
1020         if (!ast_strlen_zero(registration->transport)) {
1021                 RAII_VAR(struct ast_sip_transport *, transport, ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", registration->transport), ao2_cleanup);
1022
1023                 if (!transport || !transport->state) {
1024                         ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport '%s' "
1025                                 " for outbound registration", registration->transport);
1026                         return -1;
1027                 }
1028
1029                 if (transport->state->transport) {
1030                         selector.type = PJSIP_TPSELECTOR_TRANSPORT;
1031                         selector.u.transport = transport->state->transport;
1032                 } else if (transport->state->factory) {
1033                         selector.type = PJSIP_TPSELECTOR_LISTENER;
1034                         selector.u.listener = transport->state->factory;
1035                 } else {
1036                         return -1;
1037                 }
1038         }
1039
1040         if (!state->client_state->client
1041                 && pjsip_regc_create(ast_sip_get_pjsip_endpoint(), state->client_state,
1042                         sip_outbound_registration_response_cb,
1043                         &state->client_state->client) != PJ_SUCCESS) {
1044                 return -1;
1045         }
1046
1047         pjsip_regc_set_transport(state->client_state->client, &selector);
1048
1049         if (!ast_strlen_zero(registration->outbound_proxy)) {
1050                 pjsip_route_hdr route_set, *route;
1051                 static const pj_str_t ROUTE_HNAME = { "Route", 5 };
1052                 pj_str_t tmp;
1053
1054                 pj_list_init(&route_set);
1055
1056                 pj_strdup2_with_null(pjsip_regc_get_pool(state->client_state->client), &tmp, registration->outbound_proxy);
1057                 if (!(route = pjsip_parse_hdr(pjsip_regc_get_pool(state->client_state->client), &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
1058                         return -1;
1059                 }
1060                 pj_list_insert_nodes_before(&route_set, route);
1061
1062                 pjsip_regc_set_route_set(state->client_state->client, &route_set);
1063         }
1064
1065         if (state->registration->line) {
1066                 ast_generate_random_string(state->client_state->line, sizeof(state->client_state->line));
1067         }
1068
1069         pj_cstr(&server_uri, registration->server_uri);
1070
1071
1072         if (sip_dialog_create_contact(pjsip_regc_get_pool(state->client_state->client), &contact_uri, S_OR(registration->contact_user, "s"), &server_uri, &selector,
1073                 state->client_state->line)) {
1074                 return -1;
1075         }
1076
1077         pj_cstr(&client_uri, registration->client_uri);
1078         if (pjsip_regc_init(state->client_state->client, &server_uri, &client_uri, &client_uri, 1, &contact_uri, registration->expiration) != PJ_SUCCESS) {
1079                 return -1;
1080         }
1081
1082         return 0;
1083 }
1084
1085 /*! \brief Helper function which performs a single registration */
1086 static int sip_outbound_registration_perform(void *data)
1087 {
1088         RAII_VAR(struct sip_outbound_registration_state *, state, data, ao2_cleanup);
1089         RAII_VAR(struct sip_outbound_registration *, registration, ao2_bump(state->registration), ao2_cleanup);
1090         size_t i;
1091
1092         /* Just in case the client state is being reused for this registration, free the auth information */
1093         ast_sip_auth_vector_destroy(&state->client_state->outbound_auths);
1094
1095         AST_VECTOR_INIT(&state->client_state->outbound_auths, AST_VECTOR_SIZE(&registration->outbound_auths));
1096         for (i = 0; i < AST_VECTOR_SIZE(&registration->outbound_auths); ++i) {
1097                 const char *name = ast_strdup(AST_VECTOR_GET(&registration->outbound_auths, i));
1098                 AST_VECTOR_APPEND(&state->client_state->outbound_auths, name);
1099         }
1100         state->client_state->retry_interval = registration->retry_interval;
1101         state->client_state->forbidden_retry_interval = registration->forbidden_retry_interval;
1102         state->client_state->max_retries = registration->max_retries;
1103         state->client_state->retries = 0;
1104         state->client_state->support_path = registration->support_path;
1105         state->client_state->auth_rejection_permanent = registration->auth_rejection_permanent;
1106
1107         pjsip_regc_update_expires(state->client_state->client, registration->expiration);
1108
1109         schedule_registration(state->client_state, (ast_random() % 10) + 1);
1110
1111         return 0;
1112 }
1113
1114 /*! \brief Apply function which finds or allocates a state structure */
1115 static int sip_outbound_registration_apply(const struct ast_sorcery *sorcery, void *obj)
1116 {
1117         RAII_VAR(struct ao2_container *, states, ao2_global_obj_ref(current_states), ao2_cleanup);
1118         RAII_VAR(struct sip_outbound_registration_state *, state, NULL, ao2_cleanup);
1119         RAII_VAR(struct sip_outbound_registration_state *, new_state, NULL, ao2_cleanup);
1120         struct sip_outbound_registration *applied = obj;
1121
1122         if (!states) {
1123                 /* Global container has gone.  Likely shutting down. */
1124                 return -1;
1125         }
1126         state = ao2_find(states, ast_sorcery_object_get_id(applied), OBJ_SEARCH_KEY);
1127
1128         ast_debug(4, "Applying configuration to outbound registration '%s'\n", ast_sorcery_object_get_id(applied));
1129
1130         if (ast_strlen_zero(applied->server_uri)) {
1131                 ast_log(LOG_ERROR, "No server URI specified on outbound registration '%s'",
1132                         ast_sorcery_object_get_id(applied));
1133                 return -1;
1134         } else if (ast_strlen_zero(applied->client_uri)) {
1135                 ast_log(LOG_ERROR, "No client URI specified on outbound registration '%s'\n",
1136                         ast_sorcery_object_get_id(applied));
1137                 return -1;
1138         } else if (applied->line && ast_strlen_zero(applied->endpoint)) {
1139                 ast_log(LOG_ERROR, "Line support has been enabled on outbound registration '%s' without providing an endpoint\n",
1140                         ast_sorcery_object_get_id(applied));
1141                 return -1;
1142         } else if (!ast_strlen_zero(applied->endpoint) && !applied->line) {
1143                 ast_log(LOG_ERROR, "An endpoint has been specified on outbound registration '%s' without enabling line support\n",
1144                         ast_sorcery_object_get_id(applied));
1145                 return -1;
1146         }
1147
1148         if (state && can_reuse_registration(state->registration, applied)) {
1149                 ast_debug(4,
1150                         "No change between old configuration and new configuration on outbound registration '%s'. Using previous state\n",
1151                         ast_sorcery_object_get_id(applied));
1152
1153                 /*
1154                  * This is OK to replace without relinking the state in the
1155                  * current_states container since state->registration and
1156                  * applied have the same key.
1157                  */
1158                 ao2_lock(states);
1159                 ao2_replace(state->registration, applied);
1160                 ao2_unlock(states);
1161                 return 0;
1162         }
1163
1164         if (!(new_state = sip_outbound_registration_state_alloc(applied))) {
1165                 return -1;
1166         }
1167
1168         if (ast_sip_push_task_synchronous(NULL, sip_outbound_registration_regc_alloc, new_state)) {
1169                 return -1;
1170         }
1171
1172         if (ast_sip_push_task(new_state->client_state->serializer,
1173                               sip_outbound_registration_perform, ao2_bump(new_state))) {
1174                 ast_log(LOG_ERROR, "Failed to perform outbound registration on '%s'\n",
1175                         ast_sorcery_object_get_id(new_state->registration));
1176                 ao2_ref(new_state, -1);
1177                 return -1;
1178         }
1179
1180         ao2_lock(states);
1181
1182         if (state) {
1183                 ao2_unlink(states, state);
1184         }
1185
1186         ao2_link(states, new_state);
1187         ao2_unlock(states);
1188
1189         return 0;
1190 }
1191
1192 static int outbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
1193 {
1194         struct sip_outbound_registration *registration = obj;
1195
1196         return ast_sip_auth_vector_init(&registration->outbound_auths, var->value);
1197 }
1198
1199 static int outbound_auths_to_str(const void *obj, const intptr_t *args, char **buf)
1200 {
1201         const struct sip_outbound_registration *registration = obj;
1202
1203         return ast_sip_auths_to_str(&registration->outbound_auths, buf);
1204 }
1205
1206 static int outbound_auths_to_var_list(const void *obj, struct ast_variable **fields)
1207 {
1208         const struct sip_outbound_registration *registration = obj;
1209         int i;
1210         struct ast_variable *head = NULL;
1211
1212         for (i = 0; i < AST_VECTOR_SIZE(&registration->outbound_auths) ; i++) {
1213                 ast_variable_list_append(&head, ast_variable_new("outbound_auth",
1214                         AST_VECTOR_GET(&registration->outbound_auths, i), ""));
1215         }
1216
1217         if (head) {
1218                 *fields = head;
1219         }
1220
1221         return 0;
1222 }
1223
1224 static int unregister_task(void *obj)
1225 {
1226         RAII_VAR(struct sip_outbound_registration_state*, state, obj, ao2_cleanup);
1227         struct pjsip_regc *client = state->client_state->client;
1228         pjsip_tx_data *tdata;
1229         pjsip_regc_info info;
1230
1231         pjsip_regc_get_info(client, &info);
1232         ast_debug(1, "Unregistering contacts with server '%s' from client '%s'\n",
1233                         state->registration->server_uri, state->registration->client_uri);
1234
1235         cancel_registration(state->client_state);
1236
1237         if (pjsip_regc_unregister(client, &tdata) != PJ_SUCCESS) {
1238                 return 0;
1239         }
1240
1241         registration_client_send(state->client_state, tdata);
1242
1243         return 0;
1244 }
1245
1246 static int queue_unregister(struct sip_outbound_registration_state *state)
1247 {
1248         ao2_ref(state, +1);
1249         if (ast_sip_push_task(state->client_state->serializer, unregister_task, state)) {
1250                 ao2_ref(state, -1);
1251                 return -1;
1252         }
1253
1254         return 0;
1255 }
1256
1257 static int queue_register(struct sip_outbound_registration_state *state)
1258 {
1259         ao2_ref(state, +1);
1260         if (ast_sip_push_task(state->client_state->serializer, sip_outbound_registration_perform, state)) {
1261                 ao2_ref(state, -1);
1262                 return -1;
1263         }
1264
1265         return 0;
1266 }
1267
1268 static char *cli_complete_registration(const char *line, const char *word,
1269                                        int pos, int state)
1270 {
1271         char *result = NULL;
1272         int wordlen;
1273         int which = 0;
1274         struct sip_outbound_registration *registration;
1275         RAII_VAR(struct ao2_container *, registrations, NULL, ao2_cleanup);
1276         struct ao2_iterator i;
1277
1278         if (pos != 3) {
1279                 return NULL;
1280         }
1281
1282         wordlen = strlen(word);
1283         registrations = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "registration",
1284                 AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
1285         if (!registrations) {
1286                 return NULL;
1287         }
1288
1289         i = ao2_iterator_init(registrations, 0);
1290         while ((registration = ao2_iterator_next(&i))) {
1291                 const char *name = ast_sorcery_object_get_id(registration);
1292                 if (!strncasecmp(word, name, wordlen) && ++which > state) {
1293                         result = ast_strdup(name);
1294                 }
1295
1296                 ao2_cleanup(registration);
1297                 if (result) {
1298                         break;
1299                 }
1300         }
1301         ao2_iterator_destroy(&i);
1302         return result;
1303 }
1304
1305 static char *cli_unregister(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1306 {
1307         RAII_VAR(struct sip_outbound_registration_state *, state, NULL, ao2_cleanup);
1308         const char *registration_name;
1309
1310         switch (cmd) {
1311         case CLI_INIT:
1312                 e->command = "pjsip send unregister";
1313                 e->usage =
1314                         "Usage: pjsip send unregister <registration>\n"
1315                         "       Unregisters the specified outbound registration and stops future registration attempts.\n";
1316                 return NULL;
1317         case CLI_GENERATE:
1318                 return cli_complete_registration(a->line, a->word, a->pos, a->n);
1319         }
1320
1321         if (a->argc != 4) {
1322                 return CLI_SHOWUSAGE;
1323         }
1324
1325         registration_name = a->argv[3];
1326
1327         state = get_state(registration_name);
1328         if (!state) {
1329                 ast_cli(a->fd, "Unable to retrieve registration %s\n", registration_name);
1330                 return CLI_FAILURE;
1331         }
1332
1333         if (queue_unregister(state)) {
1334                 ast_cli(a->fd, "Failed to queue unregistration");
1335                 return 0;
1336         }
1337
1338         return CLI_SUCCESS;
1339 }
1340
1341 static char *cli_register(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1342 {
1343         RAII_VAR(struct sip_outbound_registration_state *, state, NULL, ao2_cleanup);
1344         const char *registration_name;
1345
1346         switch (cmd) {
1347         case CLI_INIT:
1348                 e->command = "pjsip send register";
1349                 e->usage =
1350                         "Usage: pjsip send register <registration>\n"
1351                         "       Unregisters the specified outbound "
1352                         "registration then re-registers and re-schedules it.\n";
1353                 return NULL;
1354         case CLI_GENERATE:
1355                 return cli_complete_registration(a->line, a->word, a->pos, a->n);
1356         }
1357
1358         if (a->argc != 4) {
1359                 return CLI_SHOWUSAGE;
1360         }
1361
1362         registration_name = a->argv[3];
1363
1364         state = get_state(registration_name);
1365         if (!state) {
1366                 ast_cli(a->fd, "Unable to retrieve registration %s\n", registration_name);
1367                 return CLI_FAILURE;
1368         }
1369
1370         /* We need to serialize the unregister and register so they need
1371          * to be queued as separate tasks.
1372          */
1373         if (queue_unregister(state)) {
1374                 ast_cli(a->fd, "Failed to queue unregistration");
1375                 return 0;
1376         }
1377         if (queue_register(state)) {
1378                 ast_cli(a->fd, "Failed to queue registration");
1379                 return 0;
1380         }
1381
1382         return CLI_SUCCESS;
1383 }
1384
1385 static int ami_unregister(struct mansession *s, const struct message *m)
1386 {
1387         const char *registration_name = astman_get_header(m, "Registration");
1388         RAII_VAR(struct sip_outbound_registration_state *, state, NULL, ao2_cleanup);
1389
1390         if (ast_strlen_zero(registration_name)) {
1391                 astman_send_error(s, m, "Registration parameter missing.");
1392                 return 0;
1393         }
1394
1395         state = get_state(registration_name);
1396         if (!state) {
1397                 astman_send_error(s, m, "Unable to retrieve registration entry\n");
1398                 return 0;
1399         }
1400
1401         if (queue_unregister(state)) {
1402                 astman_send_ack(s, m, "Failed to queue unregistration");
1403                 return 0;
1404         }
1405
1406         astman_send_ack(s, m, "Unregistration sent");
1407         return 0;
1408 }
1409
1410 static int ami_register(struct mansession *s, const struct message *m)
1411 {
1412         const char *registration_name = astman_get_header(m, "Registration");
1413         RAII_VAR(struct sip_outbound_registration_state *, state, NULL, ao2_cleanup);
1414
1415         if (ast_strlen_zero(registration_name)) {
1416                 astman_send_error(s, m, "Registration parameter missing.");
1417                 return 0;
1418         }
1419
1420         state = get_state(registration_name);
1421         if (!state) {
1422                 astman_send_error(s, m, "Unable to retrieve registration entry\n");
1423                 return 0;
1424         }
1425
1426         /* We need to serialize the unregister and register so they need
1427          * to be queued as separate tasks.
1428          */
1429         if (queue_unregister(state)) {
1430                 astman_send_ack(s, m, "Failed to queue unregistration");
1431                 return 0;
1432         }
1433         if (queue_register(state)) {
1434                 astman_send_ack(s, m, "Failed to queue unregistration");
1435                 return 0;
1436         }
1437
1438         astman_send_ack(s, m, "Reregistration sent");
1439         return 0;
1440 }
1441
1442 struct sip_ami_outbound {
1443         struct ast_sip_ami *ami;
1444         int registered;
1445         int not_registered;
1446         struct sip_outbound_registration *registration;
1447 };
1448
1449 static int ami_outbound_registration_task(void *obj)
1450 {
1451         struct sip_ami_outbound *ami = obj;
1452         RAII_VAR(struct ast_str *, buf, NULL, ast_free);
1453         struct sip_outbound_registration_state *state;
1454
1455         buf = ast_sip_create_ami_event("OutboundRegistrationDetail", ami->ami);
1456         if (!buf) {
1457                 return -1;
1458         }
1459
1460         ast_sip_sorcery_object_to_ami(ami->registration, &buf);
1461
1462         if ((state = get_state(ast_sorcery_object_get_id(ami->registration)))) {
1463                 pjsip_regc_info info;
1464
1465                 if (state->client_state->status == SIP_REGISTRATION_REGISTERED) {
1466                         ++ami->registered;
1467                 } else {
1468                         ++ami->not_registered;
1469                 }
1470
1471                 ast_str_append(&buf, 0, "Status: %s\r\n",
1472                         sip_outbound_registration_status_str[state->client_state->status]);
1473
1474                 pjsip_regc_get_info(state->client_state->client, &info);
1475                 ast_str_append(&buf, 0, "NextReg: %d\r\n", info.next_reg);
1476                 ao2_ref(state, -1);
1477         }
1478
1479         astman_append(ami->ami->s, "%s\r\n", ast_str_buffer(buf));
1480         return ast_sip_format_auths_ami(&ami->registration->outbound_auths, ami->ami);
1481 }
1482
1483 static int ami_outbound_registration_detail(void *obj, void *arg, int flags)
1484 {
1485         struct sip_ami_outbound *ami = arg;
1486
1487         ami->registration = obj;
1488         return ast_sip_push_task_synchronous(
1489                 NULL, ami_outbound_registration_task, ami);
1490 }
1491
1492 static int ami_show_outbound_registrations(struct mansession *s,
1493                                            const struct message *m)
1494 {
1495         struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
1496         struct sip_ami_outbound ami_outbound = { .ami = &ami };
1497         RAII_VAR(struct ao2_container *, regs, get_registrations(), ao2_cleanup);
1498
1499         if (!regs) {
1500                 astman_send_error(s, m, "Unable to retrieve "
1501                                   "outbound registrations\n");
1502                 return -1;
1503         }
1504
1505         astman_send_listack(s, m, "Following are Events for each Outbound registration",
1506                 "start");
1507
1508         ao2_callback(regs, OBJ_NODATA, ami_outbound_registration_detail, &ami_outbound);
1509
1510         astman_send_list_complete_start(s, m, "OutboundRegistrationDetailComplete",
1511                 ami_outbound.registered + ami_outbound.not_registered);
1512         astman_append(s,
1513                 "Registered: %d\r\n"
1514                 "NotRegistered: %d\r\n",
1515                 ami_outbound.registered,
1516                 ami_outbound.not_registered);
1517         astman_send_list_complete_end(s);
1518         return 0;
1519 }
1520
1521 static struct ao2_container *cli_get_container(void)
1522 {
1523         RAII_VAR(struct ao2_container *, container, get_registrations(), ao2_cleanup);
1524         struct ao2_container *s_container;
1525
1526         if (!container) {
1527                 return NULL;
1528         }
1529
1530         s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
1531                 ast_sorcery_object_id_sort, ast_sorcery_object_id_compare);
1532         if (!s_container) {
1533                 return NULL;
1534         }
1535
1536         if (ao2_container_dup(s_container, container, 0)) {
1537                 ao2_ref(s_container, -1);
1538                 return NULL;
1539         }
1540
1541         return s_container;
1542 }
1543
1544 static int cli_iterator(void *container, ao2_callback_fn callback, void *args)
1545 {
1546         ao2_callback(container, OBJ_NODATA, callback, args);
1547
1548         return 0;
1549 }
1550
1551 static void *cli_retrieve_by_id(const char *id)
1552 {
1553         struct ao2_container *states;
1554         void *obj = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration", id);
1555
1556         if (!obj) {
1557                 /* if the object no longer exists then remove its state  */
1558                 states = ao2_global_obj_ref(current_states);
1559                 if (states) {
1560                         ao2_find(states, id, OBJ_SEARCH_KEY | OBJ_UNLINK | OBJ_NODATA);
1561                         ao2_ref(states, -1);
1562                 }
1563         }
1564
1565         return obj;
1566 }
1567
1568 static int cli_print_header(void *obj, void *arg, int flags)
1569 {
1570         struct ast_sip_cli_context *context = arg;
1571
1572         ast_assert(context->output_buffer != NULL);
1573
1574         ast_str_append(&context->output_buffer, 0,
1575                 " <Registration/ServerURI..............................>  <Auth..........>  <Status.......>\n");
1576
1577         return 0;
1578 }
1579
1580 static int cli_print_body(void *obj, void *arg, int flags)
1581 {
1582         struct sip_outbound_registration *registration = obj;
1583         struct ast_sip_cli_context *context = arg;
1584         const char *id = ast_sorcery_object_get_id(registration);
1585         struct sip_outbound_registration_state *state = get_state(id);
1586 #define REGISTRATION_URI_FIELD_LEN      53
1587
1588         ast_assert(context->output_buffer != NULL);
1589
1590         if (!state) {
1591                 return 0;
1592         }
1593
1594         ast_str_append(&context->output_buffer, 0, " %-s/%-*.*s  %-16s  %-16s\n",
1595                 id,
1596                 (int) (REGISTRATION_URI_FIELD_LEN - strlen(id)),
1597                 (int) (REGISTRATION_URI_FIELD_LEN - strlen(id)),
1598                 registration->server_uri,
1599                 AST_VECTOR_SIZE(&registration->outbound_auths)
1600                         ? AST_VECTOR_GET(&registration->outbound_auths, 0)
1601                         : "n/a",
1602                 sip_outbound_registration_status_str[state->client_state->status]);
1603         ao2_ref(state, -1);
1604
1605         if (context->show_details
1606                 || (context->show_details_only_level_0 && context->indent_level == 0)) {
1607                 ast_str_append(&context->output_buffer, 0, "\n");
1608                 ast_sip_cli_print_sorcery_objectset(registration, context, 0);
1609         }
1610
1611         return 0;
1612 }
1613
1614 /*
1615  * A function pointer to callback needs to be within the
1616  * module in order to avoid problems with an undefined
1617  * symbol when the module is loaded.
1618  */
1619 static char *my_cli_traverse_objects(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1620 {
1621         return ast_sip_cli_traverse_objects(e, cmd, a);
1622 }
1623
1624 static struct ast_cli_entry cli_outbound_registration[] = {
1625         AST_CLI_DEFINE(cli_unregister, "Unregisters outbound registration target"),
1626         AST_CLI_DEFINE(cli_register, "Registers an outbound registration target"),
1627         AST_CLI_DEFINE(my_cli_traverse_objects, "List PJSIP Registrations",
1628                 .command = "pjsip list registrations",
1629                 .usage = "Usage: pjsip list registrations\n"
1630                                  "       List the configured PJSIP Registrations\n"),
1631         AST_CLI_DEFINE(my_cli_traverse_objects, "Show PJSIP Registrations",
1632                 .command = "pjsip show registrations",
1633                 .usage = "Usage: pjsip show registrations\n"
1634                                  "       Show the configured PJSIP Registrations\n"),
1635         AST_CLI_DEFINE(my_cli_traverse_objects, "Show PJSIP Registration",
1636                 .command = "pjsip show registration",
1637                 .usage = "Usage: pjsip show registration <id>\n"
1638                                  "       Show the configured PJSIP Registration\n"),
1639 };
1640
1641 static struct ast_sip_cli_formatter_entry *cli_formatter;
1642
1643 static void auth_observer(const char *type)
1644 {
1645         struct sip_outbound_registration *registration;
1646         struct sip_outbound_registration_state *state;
1647         struct ao2_container *regs;
1648         const char *registration_id;
1649         struct ao2_iterator i;
1650
1651         ast_debug(4, "Auths updated. Checking for any outbound registrations that are in permanent rejected state so they can be retried\n");
1652
1653         regs = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "registration",
1654                 AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
1655         if (!regs || ao2_container_count(regs) == 0) {
1656                 ao2_cleanup(regs);
1657                 return;
1658         }
1659
1660         i = ao2_iterator_init(regs, 0);
1661         for (; (registration = ao2_iterator_next(&i)); ao2_ref(registration, -1)) {
1662                 registration_id = ast_sorcery_object_get_id(registration);
1663                 state = get_state(registration_id);
1664                 if (state && state->client_state->status == SIP_REGISTRATION_REJECTED_PERMANENT) {
1665                         ast_debug(4, "Trying outbound registration '%s' again\n", registration_id);
1666
1667                         if (ast_sip_push_task(state->client_state->serializer,
1668                                               sip_outbound_registration_perform, ao2_bump(state))) {
1669                                 ast_log(LOG_ERROR, "Failed to perform outbound registration on '%s'\n", registration_id);
1670                                 ao2_ref(state, -1);
1671                         }
1672                 }
1673                 ao2_cleanup(state);
1674         }
1675         ao2_iterator_destroy(&i);
1676         ao2_cleanup(regs);
1677 }
1678
1679 static const struct ast_sorcery_observer observer_callbacks_auth = {
1680         .loaded = auth_observer,
1681 };
1682
1683 static int check_state(void *obj, void *arg, int flags)
1684 {
1685         struct sip_outbound_registration_state *state = obj;
1686         struct sip_outbound_registration *registration;
1687
1688         registration = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration",
1689                 ast_sorcery_object_get_id(state->registration));
1690         if (!registration) {
1691                 /* This is a dead registration */
1692                 return CMP_MATCH;
1693         }
1694
1695         ao2_ref(registration, -1);
1696         return 0;
1697 }
1698
1699 /*!
1700  * \internal
1701  * \brief Observer to purge dead registration states.
1702  *
1703  * \param name Module name owning the sorcery instance.
1704  * \param sorcery Instance being observed.
1705  * \param object_type Name of object being observed.
1706  * \param reloaded Non-zero if the object is being reloaded.
1707  *
1708  * \return Nothing
1709  */
1710 static void registration_loaded_observer(const char *name, const struct ast_sorcery *sorcery, const char *object_type, int reloaded)
1711 {
1712         struct ao2_container *states;
1713
1714         if (strcmp(object_type, "registration")) {
1715                 /* Not interested */
1716                 return;
1717         }
1718
1719         states = ao2_global_obj_ref(current_states);
1720         if (!states) {
1721                 /* Global container has gone.  Likely shutting down. */
1722                 return;
1723         }
1724
1725         /* Now to purge dead registrations. */
1726         ao2_callback(states, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, check_state, NULL);
1727         ao2_ref(states, -1);
1728 }
1729
1730 static const struct ast_sorcery_instance_observer observer_callbacks_registrations = {
1731         .object_type_loaded = registration_loaded_observer,
1732 };
1733
1734 static int unload_module(void)
1735 {
1736         ast_sip_unregister_endpoint_identifier(&line_identifier);
1737         ast_sorcery_observer_remove(ast_sip_get_sorcery(), "auth", &observer_callbacks_auth);
1738         ast_sorcery_instance_observer_remove(ast_sip_get_sorcery(), &observer_callbacks_registrations);
1739         ast_cli_unregister_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration));
1740         ast_sip_unregister_cli_formatter(cli_formatter);
1741         ast_manager_unregister("PJSIPShowRegistrationsOutbound");
1742         ast_manager_unregister("PJSIPUnregister");
1743         ast_manager_unregister("PJSIPRegister");
1744
1745         ao2_global_obj_release(current_states);
1746
1747         return 0;
1748 }
1749
1750 static int load_module(void)
1751 {
1752         struct ao2_container *new_states;
1753
1754         CHECK_PJSIP_MODULE_LOADED();
1755
1756         ast_sorcery_apply_config(ast_sip_get_sorcery(), "res_pjsip_outbound_registration");
1757         ast_sorcery_apply_default(ast_sip_get_sorcery(), "registration", "config", "pjsip.conf,criteria=type=registration");
1758
1759         if (ast_sorcery_object_register(ast_sip_get_sorcery(), "registration", sip_outbound_registration_alloc, NULL, sip_outbound_registration_apply)) {
1760                 return AST_MODULE_LOAD_DECLINE;
1761         }
1762
1763         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "type", "", OPT_NOOP_T, 0, 0);
1764         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "server_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, server_uri));
1765         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "client_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, client_uri));
1766         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "contact_user", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, contact_user));
1767         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, transport));
1768         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, outbound_proxy));
1769         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "expiration", "3600", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, expiration));
1770         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "retry_interval", "60", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, retry_interval));
1771         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "forbidden_retry_interval", "0", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, forbidden_retry_interval));
1772         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "max_retries", "10", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, max_retries));
1773         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "auth_rejection_permanent", "yes", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, auth_rejection_permanent));
1774         ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "registration", "outbound_auth", "", outbound_auth_handler, outbound_auths_to_str, outbound_auths_to_var_list, 0, 0);
1775         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "support_path", "no", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, support_path));
1776         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "line", "no", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, line));
1777         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "endpoint", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, endpoint));
1778         ast_sip_register_endpoint_identifier(&line_identifier);
1779
1780         ast_manager_register_xml("PJSIPUnregister", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_unregister);
1781         ast_manager_register_xml("PJSIPRegister", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_register);
1782         ast_manager_register_xml("PJSIPShowRegistrationsOutbound", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_show_outbound_registrations);
1783
1784         cli_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
1785         if (!cli_formatter) {
1786                 ast_log(LOG_ERROR, "Unable to allocate memory for cli formatter\n");
1787                 unload_module();
1788                 return AST_MODULE_LOAD_FAILURE;
1789         }
1790         cli_formatter->name = "registration";
1791         cli_formatter->print_header = cli_print_header;
1792         cli_formatter->print_body = cli_print_body;
1793         cli_formatter->get_container = cli_get_container;
1794         cli_formatter->iterate = cli_iterator;
1795         cli_formatter->get_id = ast_sorcery_object_get_id;
1796         cli_formatter->retrieve_by_id = cli_retrieve_by_id;
1797
1798         ast_sip_register_cli_formatter(cli_formatter);
1799         ast_cli_register_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration));
1800
1801         if (!(new_states = ao2_container_alloc(
1802                       DEFAULT_STATE_BUCKETS, registration_state_hash, registration_state_cmp))) {
1803                 ast_log(LOG_ERROR, "Unable to allocate registration states container\n");
1804                 unload_module();
1805                 return AST_MODULE_LOAD_FAILURE;
1806         }
1807         ao2_global_obj_replace_unref(current_states, new_states);
1808         ao2_ref(new_states, -1);
1809
1810         if (ast_sorcery_instance_observer_add(ast_sip_get_sorcery(),
1811                 &observer_callbacks_registrations)) {
1812                 unload_module();
1813                 return AST_MODULE_LOAD_FAILURE;
1814         }
1815
1816         ast_sorcery_load_object(ast_sip_get_sorcery(), "registration");
1817
1818         ast_sorcery_observer_add(ast_sip_get_sorcery(), "auth", &observer_callbacks_auth);
1819
1820         return AST_MODULE_LOAD_SUCCESS;
1821 }
1822
1823 static int reload_module(void)
1824 {
1825         ast_sorcery_reload_object(ast_sip_get_sorcery(), "registration");
1826         return 0;
1827 }
1828
1829 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Outbound Registration Support",
1830         .support_level = AST_MODULE_SUPPORT_CORE,
1831         .load = load_module,
1832         .reload = reload_module,
1833         .unload = unload_module,
1834         .load_pri = AST_MODPRI_APP_DEPEND,
1835 );