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