res_pjsip_outbound_registration.c: Add missing line endings to CLI commands
[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         struct sip_outbound_registration_state *state = NULL;
364         struct ao2_container *states;
365
366         states = ao2_global_obj_ref(current_states);
367         if (states) {
368                 state = ao2_find(states, id, OBJ_SEARCH_KEY);
369                 ao2_ref(states, -1);
370         }
371         return state;
372 }
373
374 static struct ao2_container *get_registrations(void)
375 {
376         struct ao2_container *registrations = ast_sorcery_retrieve_by_fields(
377                 ast_sip_get_sorcery(), "registration",
378                 AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
379
380         return registrations;
381 }
382
383 /*! \brief Callback function for matching an outbound registration based on line */
384 static int line_identify_relationship(void *obj, void *arg, int flags)
385 {
386         struct sip_outbound_registration_state *state = obj;
387         pjsip_param *line = arg;
388
389         return !pj_strcmp2(&line->value, state->client_state->line) ? CMP_MATCH | CMP_STOP : 0;
390 }
391
392 static struct pjsip_param *get_uri_option_line(const void *uri)
393 {
394         pjsip_sip_uri *pjuri;
395         static const pj_str_t LINE_STR = { "line", 4 };
396
397         if (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri)) {
398                 return NULL;
399         }
400         pjuri = pjsip_uri_get_uri(uri);
401         return pjsip_param_find(&pjuri->other_param, &LINE_STR);
402 }
403
404 /*! \brief Endpoint identifier which uses the 'line' parameter to establish a relationship to an outgoing registration */
405 static struct ast_sip_endpoint *line_identify(pjsip_rx_data *rdata)
406 {
407         pjsip_param *line;
408         RAII_VAR(struct ao2_container *, states, NULL, ao2_cleanup);
409         RAII_VAR(struct sip_outbound_registration_state *, state, NULL, ao2_cleanup);
410
411         if (!(line = get_uri_option_line(rdata->msg_info.to->uri))
412                 && !(line = get_uri_option_line(rdata->msg_info.msg->line.req.uri))) {
413                 return NULL;
414         }
415
416         states = ao2_global_obj_ref(current_states);
417         if (!states) {
418                 return NULL;
419         }
420
421         state = ao2_callback(states, 0, line_identify_relationship, line);
422         if (!state || ast_strlen_zero(state->registration->endpoint)) {
423                 return NULL;
424         }
425
426         ast_debug(3, "Determined relationship to outbound registration '%s' based on line '%s', using configured endpoint '%s'\n",
427                 ast_sorcery_object_get_id(state->registration), state->client_state->line, state->registration->endpoint);
428
429         return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", state->registration->endpoint);
430 }
431
432 static struct ast_sip_endpoint_identifier line_identifier = {
433         .identify_endpoint = line_identify,
434 };
435
436 /*! \brief Helper function which cancels the timer on a client */
437 static void cancel_registration(struct sip_outbound_registration_client_state *client_state)
438 {
439         if (pj_timer_heap_cancel(pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()), &client_state->timer)) {
440                 /* The timer was successfully cancelled, drop the refcount of client_state */
441                 ao2_ref(client_state, -1);
442         }
443 }
444
445 static pj_str_t PATH_NAME = { "path", 4 };
446
447 /*! \brief Helper function which sends a message and cleans up, if needed, on failure */
448 static pj_status_t registration_client_send(struct sip_outbound_registration_client_state *client_state,
449         pjsip_tx_data *tdata)
450 {
451         pj_status_t status;
452         int *callback_invoked;
453
454         callback_invoked = ast_threadstorage_get(&register_callback_invoked, sizeof(int));
455         if (!callback_invoked) {
456                 return PJ_ENOMEM;
457         }
458         *callback_invoked = 0;
459
460         /* Due to the message going out the callback may now be invoked, so bump the count */
461         ao2_ref(client_state, +1);
462         status = pjsip_regc_send(client_state->client, tdata);
463
464         /* If the attempt to send the message failed and the callback was not invoked we need to
465          * drop the reference we just added
466          */
467         if ((status != PJ_SUCCESS) && !(*callback_invoked)) {
468                 ao2_ref(client_state, -1);
469         }
470
471         return status;
472 }
473
474 /*! \brief Callback function for registering */
475 static int handle_client_registration(void *data)
476 {
477         RAII_VAR(struct sip_outbound_registration_client_state *, client_state, data, ao2_cleanup);
478         pjsip_tx_data *tdata;
479         pjsip_regc_info info;
480         char server_uri[PJSIP_MAX_URL_SIZE];
481         char client_uri[PJSIP_MAX_URL_SIZE];
482
483         if (client_state->status == SIP_REGISTRATION_STOPPED
484                 || pjsip_regc_register(client_state->client, PJ_FALSE, &tdata) != PJ_SUCCESS) {
485                 return 0;
486         }
487
488         pjsip_regc_get_info(client_state->client, &info);
489         ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
490         ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
491         ast_debug(3, "REGISTER attempt %u to '%s' with client '%s'\n",
492                   client_state->retries + 1, server_uri, client_uri);
493
494         if (client_state->support_path) {
495                 pjsip_supported_hdr *hdr;
496
497                 hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_SUPPORTED, NULL);
498                 if (!hdr) {
499                         /* insert a new Supported header */
500                         hdr = pjsip_supported_hdr_create(tdata->pool);
501                         if (!hdr) {
502                                 return -1;
503                         }
504
505                         pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)hdr);
506                 }
507
508                 /* add on to the existing Supported header */
509                 pj_strassign(&hdr->values[hdr->count++], &PATH_NAME);
510         }
511
512         registration_client_send(client_state, tdata);
513
514         return 0;
515 }
516
517 /*! \brief Timer callback function, used just for registrations */
518 static void sip_outbound_registration_timer_cb(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
519 {
520         struct sip_outbound_registration_client_state *client_state = entry->user_data;
521         pjsip_regc_info info;
522
523         pjsip_regc_get_info(client_state->client, &info);
524         ast_debug(1, "Attempting scheduled outbound registration attempt to server '%.*s' from client '%.*s'\n",
525                         (int) info.server_uri.slen, info.server_uri.ptr,
526                         (int) info.client_uri.slen, info.client_uri.ptr);
527
528         ao2_ref(client_state, +1);
529         if (ast_sip_push_task(client_state->serializer, handle_client_registration, client_state)) {
530                 ast_log(LOG_WARNING, "Scheduled outbound registration to server '%.*s' from client '%.*s' could not be executed\n",
531                                 (int) info.server_uri.slen, info.server_uri.ptr,
532                                 (int) info.client_uri.slen, info.client_uri.ptr);
533                 ao2_ref(client_state, -1);
534         }
535         ao2_ref(client_state, -1);
536
537         entry->id = 0;
538 }
539
540 /*! \brief Helper function which sets up the timer to re-register in a specific amount of time */
541 static void schedule_registration(struct sip_outbound_registration_client_state *client_state, unsigned int seconds)
542 {
543         pj_time_val delay = { .sec = seconds, };
544         pjsip_regc_info info;
545
546         cancel_registration(client_state);
547
548         pjsip_regc_get_info(client_state->client, &info);
549         ast_debug(1, "Scheduling outbound registration to server '%.*s' from client '%.*s' in %d seconds\n",
550                         (int) info.server_uri.slen, info.server_uri.ptr,
551                         (int) info.client_uri.slen, info.client_uri.ptr,
552                         seconds);
553
554         ao2_ref(client_state, +1);
555         if (pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(), &client_state->timer, &delay) != PJ_SUCCESS) {
556                 ast_log(LOG_WARNING, "Failed to schedule registration to server '%.*s' from client '%.*s'\n",
557                                 (int) info.server_uri.slen, info.server_uri.ptr,
558                                 (int) info.client_uri.slen, info.client_uri.ptr);
559                 ao2_ref(client_state, -1);
560         }
561 }
562
563 /*! \brief Callback function for unregistering (potentially) and destroying state */
564 static int handle_client_state_destruction(void *data)
565 {
566         RAII_VAR(struct sip_outbound_registration_client_state *, client_state, data, ao2_cleanup);
567
568         cancel_registration(client_state);
569
570         if (client_state->client) {
571                 pjsip_regc_info info;
572
573                 pjsip_regc_get_info(client_state->client, &info);
574
575                 if (info.is_busy == PJ_TRUE) {
576                         /* If a client transaction is in progress we defer until it is complete */
577                         client_state->destroy = 1;
578                         return 0;
579                 }
580
581                 if (client_state->status != SIP_REGISTRATION_UNREGISTERED
582                         && client_state->status != SIP_REGISTRATION_REJECTED_PERMANENT) {
583                         pjsip_tx_data *tdata;
584
585                         if (pjsip_regc_unregister(client_state->client, &tdata) == PJ_SUCCESS) {
586                                 pjsip_regc_send(client_state->client, tdata);
587                         }
588                 }
589
590                 pjsip_regc_destroy(client_state->client);
591         }
592
593         client_state->status = SIP_REGISTRATION_STOPPED;
594         ast_sip_auth_vector_destroy(&client_state->outbound_auths);
595
596         return 0;
597 }
598
599 /*! \brief Structure for registration response */
600 struct registration_response {
601         /*! \brief Response code for the registration attempt */
602         int code;
603         /*! \brief Expiration time for registration */
604         int expiration;
605         /*! \brief Retry-After value */
606         int retry_after;
607         /*! \brief Outbound registration client state */
608         struct sip_outbound_registration_client_state *client_state;
609         /*! \brief The response message */
610         pjsip_rx_data *rdata;
611         /*! \brief Request for which the response was received */
612         pjsip_tx_data *old_request;
613 };
614
615 /*! \brief Registration response structure destructor */
616 static void registration_response_destroy(void *obj)
617 {
618         struct registration_response *response = obj;
619
620         if (response->rdata) {
621                 pjsip_rx_data_free_cloned(response->rdata);
622         }
623
624         if (response->old_request) {
625                 pjsip_tx_data_dec_ref(response->old_request);
626         }
627
628         ao2_cleanup(response->client_state);
629 }
630
631 /*! \brief Helper function which determines if a response code is temporal or not */
632 static int sip_outbound_registration_is_temporal(unsigned int code,
633                 struct sip_outbound_registration_client_state *client_state)
634 {
635         /* Shamelessly taken from pjsua */
636         if (code == PJSIP_SC_REQUEST_TIMEOUT ||
637                 code == PJSIP_SC_INTERNAL_SERVER_ERROR ||
638                 code == PJSIP_SC_BAD_GATEWAY ||
639                 code == PJSIP_SC_SERVICE_UNAVAILABLE ||
640                 code == PJSIP_SC_SERVER_TIMEOUT ||
641                 ((code == PJSIP_SC_UNAUTHORIZED ||
642                   code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED) &&
643                  !client_state->auth_rejection_permanent) ||
644                 PJSIP_IS_STATUS_IN_CLASS(code, 600)) {
645                 return 1;
646         } else {
647                 return 0;
648         }
649 }
650
651 static void schedule_retry(struct registration_response *response, unsigned int interval,
652                            const char *server_uri, const char *client_uri)
653 {
654         response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY;
655         schedule_registration(response->client_state, interval);
656
657         if (response->rdata) {
658                 ast_log(LOG_WARNING, "Temporal response '%d' received from '%s' on "
659                         "registration attempt to '%s', retrying in '%u'\n",
660                         response->code, server_uri, client_uri, interval);
661         } else {
662                 ast_log(LOG_WARNING, "No response received from '%s' on "
663                         "registration attempt to '%s', retrying in '%u'\n",
664                         server_uri, client_uri, interval);
665         }
666 }
667
668 /*! \brief Callback function for handling a response to a registration attempt */
669 static int handle_registration_response(void *data)
670 {
671         RAII_VAR(struct registration_response *, response, data, ao2_cleanup);
672         pjsip_regc_info info;
673         char server_uri[PJSIP_MAX_URL_SIZE];
674         char client_uri[PJSIP_MAX_URL_SIZE];
675
676         pjsip_regc_get_info(response->client_state->client, &info);
677         ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
678         ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
679
680         if (response->client_state->status == SIP_REGISTRATION_STOPPED) {
681                 ast_debug(1, "Not handling registration response from server '%s' for client '%s'. Registration already stopped\n",
682                                 server_uri, client_uri);
683                 return 0;
684         }
685
686         ast_debug(1, "Processing REGISTER response %d from server '%s' for client '%s'\n",
687                         response->code, server_uri, client_uri);
688
689         if (!response->client_state->auth_attempted &&
690                         (response->code == 401 || response->code == 407)) {
691                 pjsip_tx_data *tdata;
692                 if (!ast_sip_create_request_with_auth(&response->client_state->outbound_auths,
693                                 response->rdata, response->old_request, &tdata)) {
694                         response->client_state->auth_attempted = 1;
695                         ast_debug(1, "Sending authenticated REGISTER to server '%s' from client '%s'\n",
696                                         server_uri, client_uri);
697                         if (registration_client_send(response->client_state, tdata) != PJ_SUCCESS) {
698                                 response->client_state->auth_attempted = 0;
699                         }
700                         return 0;
701                 } else {
702                         ast_log(LOG_WARNING, "Failed to create authenticated REGISTER request to server '%s' from client '%s'\n",
703                                         server_uri, client_uri);
704                 }
705                 /* Otherwise, fall through so the failure is processed appropriately */
706         }
707
708         response->client_state->auth_attempted = 0;
709
710         if (PJSIP_IS_STATUS_IN_CLASS(response->code, 200)) {
711                 /* Check if this is in regards to registering or unregistering */
712                 if (response->expiration) {
713                         /* If the registration went fine simply reschedule registration for the future */
714                         ast_debug(1, "Outbound registration to '%s' with client '%s' successful\n", server_uri, client_uri);
715                         response->client_state->status = SIP_REGISTRATION_REGISTERED;
716                         response->client_state->retries = 0;
717                         schedule_registration(response->client_state, response->expiration - REREGISTER_BUFFER_TIME);
718                 } else {
719                         ast_debug(1, "Outbound unregistration to '%s' with client '%s' successful\n", server_uri, client_uri);
720                         response->client_state->status = SIP_REGISTRATION_UNREGISTERED;
721                 }
722         } else if (response->retry_after) {
723                 /* If we have been instructed to retry after a period of time, schedule it as such */
724                 schedule_retry(response, response->retry_after, server_uri, client_uri);
725         } else if (response->client_state->retry_interval
726                 && sip_outbound_registration_is_temporal(response->code, response->client_state)) {
727                 if (response->client_state->retries == response->client_state->max_retries) {
728                         /* If we received enough temporal responses to exceed our maximum give up permanently */
729                         response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT;
730                         ast_log(LOG_WARNING, "Maximum retries reached when attempting outbound registration to '%s' with client '%s', stopping registration attempt\n",
731                                 server_uri, client_uri);
732                 } else {
733                         /* On the other hand if we can still try some more do so */
734                         response->client_state->retries++;
735                         schedule_retry(response, response->client_state->retry_interval, server_uri, client_uri);
736                 }
737         } else {
738                 if (response->code == 403
739                         && response->client_state->forbidden_retry_interval
740                         && response->client_state->retries < response->client_state->max_retries) {
741                         /* A forbidden response retry interval is configured and there are retries remaining */
742                         response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY;
743                         response->client_state->retries++;
744                         schedule_registration(response->client_state, response->client_state->forbidden_retry_interval);
745                         ast_log(LOG_WARNING, "403 Forbidden fatal response received from '%s' on registration attempt to '%s', retrying in '%u' seconds\n",
746                                 server_uri, client_uri, response->client_state->forbidden_retry_interval);
747                 } else {
748                         /* Finally if there's no hope of registering give up */
749                         response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT;
750                         if (response->rdata) {
751                                 ast_log(LOG_WARNING, "Fatal response '%d' received from '%s' on registration attempt to '%s', stopping outbound registration\n",
752                                         response->code, server_uri, client_uri);
753                         } else {
754                                 ast_log(LOG_WARNING, "Fatal registration attempt to '%s', stopping outbound registration\n", client_uri);
755                         }
756                 }
757         }
758
759         ast_system_publish_registry("PJSIP", client_uri, server_uri,
760                 sip_outbound_registration_status_str[response->client_state->status], NULL);
761
762         /* If deferred destruction is in use see if we need to destroy now */
763         if (response->client_state->destroy) {
764                 handle_client_state_destruction(response->client_state);
765         }
766
767         return 0;
768 }
769
770 /*! \brief Callback function for outbound registration client */
771 static void sip_outbound_registration_response_cb(struct pjsip_regc_cbparam *param)
772 {
773         RAII_VAR(struct sip_outbound_registration_client_state *, client_state, param->token, ao2_cleanup);
774         struct registration_response *response;
775         pjsip_regc_info info;
776         int *callback_invoked;
777
778         callback_invoked = ast_threadstorage_get(&register_callback_invoked, sizeof(int));
779
780         ast_assert(callback_invoked != NULL);
781         ast_assert(client_state != NULL);
782
783         *callback_invoked = 1;
784
785         response = ao2_alloc(sizeof(*response), registration_response_destroy);
786         if (!response) {
787                 return;
788         }
789         response->code = param->code;
790         response->expiration = param->expiration;
791         response->client_state = client_state;
792         ao2_ref(response->client_state, +1);
793
794         pjsip_regc_get_info(client_state->client, &info);
795         ast_debug(1, "Received REGISTER response %d(%.*s) from server '%.*s' for client '%.*s\n",
796                         param->code, (int) param->reason.slen, param->reason.ptr,
797                         (int) info.server_uri.slen, info.server_uri.ptr,
798                         (int) info.client_uri.slen, info.client_uri.ptr);
799
800         if (param->rdata) {
801                 struct pjsip_retry_after_hdr *retry_after;
802                 pjsip_transaction *tsx;
803
804                 retry_after = pjsip_msg_find_hdr(param->rdata->msg_info.msg, PJSIP_H_RETRY_AFTER,
805                         NULL);
806                 response->retry_after = retry_after ? retry_after->ivalue : 0;
807                 tsx = pjsip_rdata_get_tsx(param->rdata);
808                 response->old_request = tsx->last_tx;
809                 pjsip_tx_data_add_ref(response->old_request);
810                 pjsip_rx_data_clone(param->rdata, 0, &response->rdata);
811         }
812
813         if (ast_sip_push_task(client_state->serializer, handle_registration_response, response)) {
814                 ast_log(LOG_WARNING, "Failed to pass incoming registration response to threadpool\n");
815                 ao2_cleanup(response);
816         }
817 }
818
819 /*! \brief Destructor function for registration state */
820 static void sip_outbound_registration_state_destroy(void *obj)
821 {
822         struct sip_outbound_registration_state *state = obj;
823
824         ast_debug(3, "Destroying registration state for registration to server '%s' from client '%s'\n",
825                         state->registration->server_uri, state->registration->client_uri);
826
827         ao2_cleanup(state->registration);
828
829         if (!state->client_state) {
830                 /* Nothing to do */
831         } else if (!state->client_state->serializer) {
832                 ao2_ref(state->client_state, -1);
833         } else if (ast_sip_push_task(state->client_state->serializer,
834                 handle_client_state_destruction, state->client_state)) {
835                 ast_log(LOG_WARNING, "Failed to pass outbound registration client destruction to threadpool\n");
836                 ao2_ref(state->client_state, -1);
837         }
838 }
839
840 /*! \brief Destructor function for client registration state */
841 static void sip_outbound_registration_client_state_destroy(void *obj)
842 {
843         struct sip_outbound_registration_client_state *client_state = obj;
844
845         ast_taskprocessor_unreference(client_state->serializer);
846 }
847
848 /*! \brief Allocator function for registration state */
849 static struct sip_outbound_registration_state *sip_outbound_registration_state_alloc(struct sip_outbound_registration *registration)
850 {
851         struct sip_outbound_registration_state *state;
852
853         state = ao2_alloc(sizeof(*state), sip_outbound_registration_state_destroy);
854         if (!state) {
855                 return NULL;
856         }
857         state->client_state = ao2_alloc(sizeof(*state->client_state),
858                 sip_outbound_registration_client_state_destroy);
859         if (!state->client_state) {
860                 ao2_cleanup(state);
861                 return NULL;
862         }
863
864         state->client_state->serializer = ast_sip_create_serializer();
865         if (!state->client_state->serializer) {
866                 ao2_cleanup(state);
867                 return NULL;
868         }
869         state->client_state->status = SIP_REGISTRATION_UNREGISTERED;
870         state->client_state->timer.user_data = state->client_state;
871         state->client_state->timer.cb = sip_outbound_registration_timer_cb;
872
873         state->registration = ao2_bump(registration);
874         return state;
875 }
876
877 /*! \brief Destructor function for registration information */
878 static void sip_outbound_registration_destroy(void *obj)
879 {
880         struct sip_outbound_registration *registration = obj;
881
882         ast_sip_auth_vector_destroy(&registration->outbound_auths);
883
884         ast_string_field_free_memory(registration);
885 }
886
887 /*! \brief Allocator function for registration information */
888 static void *sip_outbound_registration_alloc(const char *name)
889 {
890         struct sip_outbound_registration *registration;
891
892         registration = ast_sorcery_generic_alloc(sizeof(*registration),
893                 sip_outbound_registration_destroy);
894         if (!registration || ast_string_field_init(registration, 256)) {
895                 ao2_cleanup(registration);
896                 return NULL;
897         }
898
899         return registration;
900 }
901
902 /*! \brief Helper function which populates a pj_str_t with a contact header */
903 static int sip_dialog_create_contact(pj_pool_t *pool, pj_str_t *contact, const char *user,
904         const pj_str_t *target, pjsip_tpselector *selector, const char *line)
905 {
906         pj_str_t tmp, local_addr;
907         pjsip_uri *uri;
908         pjsip_sip_uri *sip_uri;
909         pjsip_transport_type_e type = PJSIP_TRANSPORT_UNSPECIFIED;
910         int local_port;
911
912         pj_strdup_with_null(pool, &tmp, target);
913
914         if (!(uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0)) ||
915             (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
916                 return -1;
917         }
918
919         sip_uri = pjsip_uri_get_uri(uri);
920
921         if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
922                 type = PJSIP_TRANSPORT_TLS;
923         } else if (!sip_uri->transport_param.slen) {
924                 type = PJSIP_TRANSPORT_UDP;
925         } else {
926                 type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
927         }
928
929         if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
930                 return -1;
931         }
932
933         if (pj_strchr(&sip_uri->host, ':')) {
934                 type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
935         }
936
937         if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()),
938                 pool, type, selector, &local_addr, &local_port) != PJ_SUCCESS) {
939                 return -1;
940         }
941
942         if (!pj_strchr(&sip_uri->host, ':') && pj_strchr(&local_addr, ':')) {
943                 type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
944         }
945
946         contact->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
947         contact->slen = pj_ansi_snprintf(contact->ptr, PJSIP_MAX_URL_SIZE,
948                 "<%s:%s@%s%.*s%s:%d%s%s%s%s>",
949                 (pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE) ? "sips" : "sip",
950                 user,
951                 (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
952                 (int)local_addr.slen,
953                 local_addr.ptr,
954                 (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
955                 local_port,
956                 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
957                 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "",
958                 !ast_strlen_zero(line) ? ";line=" : "",
959                 S_OR(line, ""));
960
961         return 0;
962 }
963
964 /*!
965  * \internal
966  * \brief Check if a registration can be reused
967  *
968  * This checks if the existing outbound registration's configuration differs from a newly-applied
969  * outbound registration to see if the applied one.
970  *
971  * \param existing The pre-existing outbound registration
972  * \param applied The newly-created registration
973  */
974 static int can_reuse_registration(struct sip_outbound_registration *existing,
975         struct sip_outbound_registration *applied)
976 {
977         int rc = 1;
978         struct ast_sorcery *sorcery = ast_sip_get_sorcery();
979         struct ast_variable *ve = ast_sorcery_objectset_create(sorcery, existing);
980         struct ast_variable *va = ast_sorcery_objectset_create(sorcery, applied);
981         struct ast_variable *vc = NULL;
982
983         if (ast_sorcery_changeset_create(ve, va, &vc) || vc != NULL) {
984                 rc = 0;
985                 ast_debug(4, "Registration '%s' changed.  Can't re-use.\n", ast_sorcery_object_get_id(existing));
986         } else {
987                 ast_debug(4, "Registration '%s' didn't change.  Can re-use\n", ast_sorcery_object_get_id(existing));
988         }
989
990         ast_variables_destroy(ve);
991         ast_variables_destroy(va);
992         ast_variables_destroy(vc);
993
994         return rc;
995 }
996
997 /*! \brief Helper function that allocates a pjsip registration client and configures it */
998 static int sip_outbound_registration_regc_alloc(void *data)
999 {
1000         struct sip_outbound_registration_state *state = data;
1001         RAII_VAR(struct sip_outbound_registration *, registration,
1002                  ao2_bump(state->registration), ao2_cleanup);
1003         pj_pool_t *pool;
1004         pj_str_t tmp;
1005         pjsip_uri *uri;
1006         pj_str_t server_uri, client_uri, contact_uri;
1007         pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
1008
1009         pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "URI Validation", 256, 256);
1010         if (!pool) {
1011                 ast_log(LOG_ERROR, "Could not create pool for URI validation on outbound registration '%s'\n",
1012                         ast_sorcery_object_get_id(registration));
1013                 return -1;
1014         }
1015
1016         pj_strdup2_with_null(pool, &tmp, registration->server_uri);
1017         uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0);
1018         if (!uri) {
1019                 ast_log(LOG_ERROR, "Invalid server URI '%s' specified on outbound registration '%s'\n",
1020                         registration->server_uri, ast_sorcery_object_get_id(registration));
1021                 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1022                 return -1;
1023         }
1024
1025         pj_strdup2_with_null(pool, &tmp, registration->client_uri);
1026         uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0);
1027         if (!uri) {
1028                 ast_log(LOG_ERROR, "Invalid client URI '%s' specified on outbound registration '%s'\n",
1029                         registration->client_uri, ast_sorcery_object_get_id(registration));
1030                 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1031                 return -1;
1032         }
1033
1034         pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1035
1036         if (!ast_strlen_zero(registration->transport)) {
1037                 RAII_VAR(struct ast_sip_transport *, transport, ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", registration->transport), ao2_cleanup);
1038
1039                 if (!transport || !transport->state) {
1040                         ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport '%s' "
1041                                 " for outbound registration", registration->transport);
1042                         return -1;
1043                 }
1044
1045                 if (transport->state->transport) {
1046                         selector.type = PJSIP_TPSELECTOR_TRANSPORT;
1047                         selector.u.transport = transport->state->transport;
1048                 } else if (transport->state->factory) {
1049                         selector.type = PJSIP_TPSELECTOR_LISTENER;
1050                         selector.u.listener = transport->state->factory;
1051                 } else {
1052                         return -1;
1053                 }
1054         }
1055
1056         if (!state->client_state->client
1057                 && pjsip_regc_create(ast_sip_get_pjsip_endpoint(), state->client_state,
1058                         sip_outbound_registration_response_cb,
1059                         &state->client_state->client) != PJ_SUCCESS) {
1060                 return -1;
1061         }
1062
1063         pjsip_regc_set_transport(state->client_state->client, &selector);
1064
1065         if (!ast_strlen_zero(registration->outbound_proxy)) {
1066                 pjsip_route_hdr route_set, *route;
1067                 static const pj_str_t ROUTE_HNAME = { "Route", 5 };
1068                 pj_str_t tmp;
1069
1070                 pj_list_init(&route_set);
1071
1072                 pj_strdup2_with_null(pjsip_regc_get_pool(state->client_state->client), &tmp,
1073                         registration->outbound_proxy);
1074                 route = pjsip_parse_hdr(pjsip_regc_get_pool(state->client_state->client),
1075                         &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL);
1076                 if (!route) {
1077                         return -1;
1078                 }
1079                 pj_list_insert_nodes_before(&route_set, route);
1080
1081                 pjsip_regc_set_route_set(state->client_state->client, &route_set);
1082         }
1083
1084         if (state->registration->line) {
1085                 ast_generate_random_string(state->client_state->line, sizeof(state->client_state->line));
1086         }
1087
1088         pj_cstr(&server_uri, registration->server_uri);
1089
1090
1091         if (sip_dialog_create_contact(pjsip_regc_get_pool(state->client_state->client),
1092                 &contact_uri, S_OR(registration->contact_user, "s"), &server_uri, &selector,
1093                 state->client_state->line)) {
1094                 return -1;
1095         }
1096
1097         pj_cstr(&client_uri, registration->client_uri);
1098         if (pjsip_regc_init(state->client_state->client, &server_uri, &client_uri,
1099                 &client_uri, 1, &contact_uri, registration->expiration) != PJ_SUCCESS) {
1100                 return -1;
1101         }
1102
1103         return 0;
1104 }
1105
1106 /*! \brief Helper function which performs a single registration */
1107 static int sip_outbound_registration_perform(void *data)
1108 {
1109         struct sip_outbound_registration_state *state = data;
1110         struct sip_outbound_registration *registration = ao2_bump(state->registration);
1111         size_t i;
1112
1113         /* Just in case the client state is being reused for this registration, free the auth information */
1114         ast_sip_auth_vector_destroy(&state->client_state->outbound_auths);
1115
1116         AST_VECTOR_INIT(&state->client_state->outbound_auths, AST_VECTOR_SIZE(&registration->outbound_auths));
1117         for (i = 0; i < AST_VECTOR_SIZE(&registration->outbound_auths); ++i) {
1118                 const char *name = ast_strdup(AST_VECTOR_GET(&registration->outbound_auths, i));
1119
1120                 if (name) {
1121                         AST_VECTOR_APPEND(&state->client_state->outbound_auths, name);
1122                 }
1123         }
1124         state->client_state->retry_interval = registration->retry_interval;
1125         state->client_state->forbidden_retry_interval = registration->forbidden_retry_interval;
1126         state->client_state->max_retries = registration->max_retries;
1127         state->client_state->retries = 0;
1128         state->client_state->support_path = registration->support_path;
1129         state->client_state->auth_rejection_permanent = registration->auth_rejection_permanent;
1130
1131         pjsip_regc_update_expires(state->client_state->client, registration->expiration);
1132
1133         schedule_registration(state->client_state, (ast_random() % 10) + 1);
1134
1135         ao2_ref(registration, -1);
1136         ao2_ref(state, -1);
1137         return 0;
1138 }
1139
1140 /*! \brief Apply function which finds or allocates a state structure */
1141 static int sip_outbound_registration_apply(const struct ast_sorcery *sorcery, void *obj)
1142 {
1143         RAII_VAR(struct ao2_container *, states, ao2_global_obj_ref(current_states), ao2_cleanup);
1144         RAII_VAR(struct sip_outbound_registration_state *, state, NULL, ao2_cleanup);
1145         RAII_VAR(struct sip_outbound_registration_state *, new_state, NULL, ao2_cleanup);
1146         struct sip_outbound_registration *applied = obj;
1147
1148         if (!states) {
1149                 /* Global container has gone.  Likely shutting down. */
1150                 return -1;
1151         }
1152         state = ao2_find(states, ast_sorcery_object_get_id(applied), OBJ_SEARCH_KEY);
1153
1154         ast_debug(4, "Applying configuration to outbound registration '%s'\n", ast_sorcery_object_get_id(applied));
1155
1156         if (ast_strlen_zero(applied->server_uri)) {
1157                 ast_log(LOG_ERROR, "No server URI specified on outbound registration '%s'",
1158                         ast_sorcery_object_get_id(applied));
1159                 return -1;
1160         } else if (ast_strlen_zero(applied->client_uri)) {
1161                 ast_log(LOG_ERROR, "No client URI specified on outbound registration '%s'\n",
1162                         ast_sorcery_object_get_id(applied));
1163                 return -1;
1164         } else if (applied->line && ast_strlen_zero(applied->endpoint)) {
1165                 ast_log(LOG_ERROR, "Line support has been enabled on outbound registration '%s' without providing an endpoint\n",
1166                         ast_sorcery_object_get_id(applied));
1167                 return -1;
1168         } else if (!ast_strlen_zero(applied->endpoint) && !applied->line) {
1169                 ast_log(LOG_ERROR, "An endpoint has been specified on outbound registration '%s' without enabling line support\n",
1170                         ast_sorcery_object_get_id(applied));
1171                 return -1;
1172         }
1173
1174         if (state && can_reuse_registration(state->registration, applied)) {
1175                 ast_debug(4,
1176                         "No change between old configuration and new configuration on outbound registration '%s'. Using previous state\n",
1177                         ast_sorcery_object_get_id(applied));
1178
1179                 /*
1180                  * This is OK to replace without relinking the state in the
1181                  * current_states container since state->registration and
1182                  * applied have the same key.
1183                  */
1184                 ao2_lock(states);
1185                 ao2_replace(state->registration, applied);
1186                 ao2_unlock(states);
1187                 return 0;
1188         }
1189
1190         if (!(new_state = sip_outbound_registration_state_alloc(applied))) {
1191                 return -1;
1192         }
1193
1194         if (ast_sip_push_task_synchronous(NULL, sip_outbound_registration_regc_alloc, new_state)) {
1195                 return -1;
1196         }
1197
1198         if (ast_sip_push_task(new_state->client_state->serializer,
1199                               sip_outbound_registration_perform, ao2_bump(new_state))) {
1200                 ast_log(LOG_ERROR, "Failed to perform outbound registration on '%s'\n",
1201                         ast_sorcery_object_get_id(new_state->registration));
1202                 ao2_ref(new_state, -1);
1203                 return -1;
1204         }
1205
1206         ao2_lock(states);
1207         if (state) {
1208                 ao2_unlink(states, state);
1209         }
1210         ao2_link(states, new_state);
1211         ao2_unlock(states);
1212
1213         return 0;
1214 }
1215
1216 static int outbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
1217 {
1218         struct sip_outbound_registration *registration = obj;
1219
1220         return ast_sip_auth_vector_init(&registration->outbound_auths, var->value);
1221 }
1222
1223 static int outbound_auths_to_str(const void *obj, const intptr_t *args, char **buf)
1224 {
1225         const struct sip_outbound_registration *registration = obj;
1226
1227         return ast_sip_auths_to_str(&registration->outbound_auths, buf);
1228 }
1229
1230 static int outbound_auths_to_var_list(const void *obj, struct ast_variable **fields)
1231 {
1232         const struct sip_outbound_registration *registration = obj;
1233         int i;
1234         struct ast_variable *head = NULL;
1235
1236         for (i = 0; i < AST_VECTOR_SIZE(&registration->outbound_auths) ; i++) {
1237                 ast_variable_list_append(&head, ast_variable_new("outbound_auth",
1238                         AST_VECTOR_GET(&registration->outbound_auths, i), ""));
1239         }
1240
1241         if (head) {
1242                 *fields = head;
1243         }
1244
1245         return 0;
1246 }
1247
1248 static int unregister_task(void *obj)
1249 {
1250         struct sip_outbound_registration_state *state = obj;
1251         struct pjsip_regc *client = state->client_state->client;
1252         pjsip_tx_data *tdata;
1253         pjsip_regc_info info;
1254
1255         pjsip_regc_get_info(client, &info);
1256         ast_debug(1, "Unregistering contacts with server '%s' from client '%s'\n",
1257                 state->registration->server_uri, state->registration->client_uri);
1258
1259         cancel_registration(state->client_state);
1260
1261         if (pjsip_regc_unregister(client, &tdata) == PJ_SUCCESS) {
1262                 registration_client_send(state->client_state, tdata);
1263         }
1264
1265         ao2_ref(state, -1);
1266         return 0;
1267 }
1268
1269 static int queue_unregister(struct sip_outbound_registration_state *state)
1270 {
1271         ao2_ref(state, +1);
1272         if (ast_sip_push_task(state->client_state->serializer, unregister_task, state)) {
1273                 ao2_ref(state, -1);
1274                 return -1;
1275         }
1276
1277         return 0;
1278 }
1279
1280 static int queue_register(struct sip_outbound_registration_state *state)
1281 {
1282         ao2_ref(state, +1);
1283         if (ast_sip_push_task(state->client_state->serializer, sip_outbound_registration_perform, state)) {
1284                 ao2_ref(state, -1);
1285                 return -1;
1286         }
1287
1288         return 0;
1289 }
1290
1291 static char *cli_complete_registration(const char *line, const char *word,
1292                                        int pos, int state)
1293 {
1294         char *result = NULL;
1295         int wordlen;
1296         int which = 0;
1297         struct sip_outbound_registration *registration;
1298         struct ao2_container *registrations;
1299         struct ao2_iterator i;
1300
1301         if (pos != 3) {
1302                 return NULL;
1303         }
1304
1305         wordlen = strlen(word);
1306         registrations = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "registration",
1307                 AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
1308         if (!registrations) {
1309                 return NULL;
1310         }
1311
1312         i = ao2_iterator_init(registrations, 0);
1313         while ((registration = ao2_iterator_next(&i))) {
1314                 const char *name = ast_sorcery_object_get_id(registration);
1315
1316                 if (!strncasecmp(word, name, wordlen) && ++which > state) {
1317                         result = ast_strdup(name);
1318                 }
1319
1320                 ao2_ref(registration, -1);
1321                 if (result) {
1322                         break;
1323                 }
1324         }
1325         ao2_iterator_destroy(&i);
1326
1327         ao2_ref(registrations, -1);
1328         return result;
1329 }
1330
1331 static char *cli_unregister(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1332 {
1333         struct sip_outbound_registration_state *state;
1334         const char *registration_name;
1335
1336         switch (cmd) {
1337         case CLI_INIT:
1338                 e->command = "pjsip send unregister";
1339                 e->usage =
1340                         "Usage: pjsip send unregister <registration>\n"
1341                         "       Unregisters the specified outbound registration and stops future registration attempts.\n";
1342                 return NULL;
1343         case CLI_GENERATE:
1344                 return cli_complete_registration(a->line, a->word, a->pos, a->n);
1345         }
1346
1347         if (a->argc != 4) {
1348                 return CLI_SHOWUSAGE;
1349         }
1350
1351         registration_name = a->argv[3];
1352
1353         state = get_state(registration_name);
1354         if (!state) {
1355                 ast_cli(a->fd, "Unable to retrieve registration %s\n", registration_name);
1356                 return CLI_FAILURE;
1357         }
1358
1359         if (queue_unregister(state)) {
1360                 ast_cli(a->fd, "Failed to queue unregistration\n");
1361         }
1362
1363         ao2_ref(state, -1);
1364         return CLI_SUCCESS;
1365 }
1366
1367 static char *cli_register(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1368 {
1369         struct sip_outbound_registration_state *state;
1370         const char *registration_name;
1371
1372         switch (cmd) {
1373         case CLI_INIT:
1374                 e->command = "pjsip send register";
1375                 e->usage =
1376                         "Usage: pjsip send register <registration>\n"
1377                         "       Unregisters the specified outbound "
1378                         "registration then re-registers and re-schedules it.\n";
1379                 return NULL;
1380         case CLI_GENERATE:
1381                 return cli_complete_registration(a->line, a->word, a->pos, a->n);
1382         }
1383
1384         if (a->argc != 4) {
1385                 return CLI_SHOWUSAGE;
1386         }
1387
1388         registration_name = a->argv[3];
1389
1390         state = get_state(registration_name);
1391         if (!state) {
1392                 ast_cli(a->fd, "Unable to retrieve registration %s\n", registration_name);
1393                 return CLI_FAILURE;
1394         }
1395
1396         /* We need to serialize the unregister and register so they need
1397          * to be queued as separate tasks.
1398          */
1399         if (queue_unregister(state)) {
1400                 ast_cli(a->fd, "Failed to queue unregistration\n");
1401         } else if (queue_register(state)) {
1402                 ast_cli(a->fd, "Failed to queue registration\n");
1403         }
1404
1405         ao2_ref(state, -1);
1406         return CLI_SUCCESS;
1407 }
1408
1409 static int ami_unregister(struct mansession *s, const struct message *m)
1410 {
1411         const char *registration_name = astman_get_header(m, "Registration");
1412         struct sip_outbound_registration_state *state;
1413
1414         if (ast_strlen_zero(registration_name)) {
1415                 astman_send_error(s, m, "Registration parameter missing.");
1416                 return 0;
1417         }
1418
1419         state = get_state(registration_name);
1420         if (!state) {
1421                 astman_send_error(s, m, "Unable to retrieve registration entry\n");
1422                 return 0;
1423         }
1424
1425         if (queue_unregister(state)) {
1426                 astman_send_ack(s, m, "Failed to queue unregistration");
1427         } else {
1428                 astman_send_ack(s, m, "Unregistration sent");
1429         }
1430
1431         ao2_ref(state, -1);
1432         return 0;
1433 }
1434
1435 static int ami_register(struct mansession *s, const struct message *m)
1436 {
1437         const char *registration_name = astman_get_header(m, "Registration");
1438         struct sip_outbound_registration_state *state;
1439
1440         if (ast_strlen_zero(registration_name)) {
1441                 astman_send_error(s, m, "Registration parameter missing.");
1442                 return 0;
1443         }
1444
1445         state = get_state(registration_name);
1446         if (!state) {
1447                 astman_send_error(s, m, "Unable to retrieve registration entry\n");
1448                 return 0;
1449         }
1450
1451         /* We need to serialize the unregister and register so they need
1452          * to be queued as separate tasks.
1453          */
1454         if (queue_unregister(state)) {
1455                 astman_send_ack(s, m, "Failed to queue unregistration");
1456         } else if (queue_register(state)) {
1457                 astman_send_ack(s, m, "Failed to queue unregistration");
1458         } else {
1459                 astman_send_ack(s, m, "Reregistration sent");
1460         }
1461
1462         ao2_ref(state, -1);
1463         return 0;
1464 }
1465
1466 struct sip_ami_outbound {
1467         struct ast_sip_ami *ami;
1468         int registered;
1469         int not_registered;
1470         struct sip_outbound_registration *registration;
1471 };
1472
1473 static int ami_outbound_registration_task(void *obj)
1474 {
1475         struct sip_ami_outbound *ami = obj;
1476         struct ast_str *buf;
1477         struct sip_outbound_registration_state *state;
1478
1479         buf = ast_sip_create_ami_event("OutboundRegistrationDetail", ami->ami);
1480         if (!buf) {
1481                 return -1;
1482         }
1483
1484         ast_sip_sorcery_object_to_ami(ami->registration, &buf);
1485
1486         if ((state = get_state(ast_sorcery_object_get_id(ami->registration)))) {
1487                 pjsip_regc_info info;
1488
1489                 if (state->client_state->status == SIP_REGISTRATION_REGISTERED) {
1490                         ++ami->registered;
1491                 } else {
1492                         ++ami->not_registered;
1493                 }
1494
1495                 ast_str_append(&buf, 0, "Status: %s\r\n",
1496                         sip_outbound_registration_status_str[state->client_state->status]);
1497
1498                 pjsip_regc_get_info(state->client_state->client, &info);
1499                 ast_str_append(&buf, 0, "NextReg: %d\r\n", info.next_reg);
1500                 ao2_ref(state, -1);
1501         }
1502
1503         astman_append(ami->ami->s, "%s\r\n", ast_str_buffer(buf));
1504         ast_free(buf);
1505
1506         return ast_sip_format_auths_ami(&ami->registration->outbound_auths, ami->ami);
1507 }
1508
1509 static int ami_outbound_registration_detail(void *obj, void *arg, int flags)
1510 {
1511         struct sip_ami_outbound *ami = arg;
1512
1513         ami->registration = obj;
1514         return ast_sip_push_task_synchronous(
1515                 NULL, ami_outbound_registration_task, ami);
1516 }
1517
1518 static int ami_show_outbound_registrations(struct mansession *s,
1519                                            const struct message *m)
1520 {
1521         struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
1522         struct sip_ami_outbound ami_outbound = { .ami = &ami };
1523         struct ao2_container *regs;
1524
1525         regs = get_registrations();
1526         if (!regs) {
1527                 astman_send_error(s, m, "Unable to retrieve "
1528                                   "outbound registrations\n");
1529                 return -1;
1530         }
1531
1532         astman_send_listack(s, m, "Following are Events for each Outbound registration",
1533                 "start");
1534
1535         ao2_callback(regs, OBJ_NODATA, ami_outbound_registration_detail, &ami_outbound);
1536
1537         astman_send_list_complete_start(s, m, "OutboundRegistrationDetailComplete",
1538                 ami_outbound.registered + ami_outbound.not_registered);
1539         astman_append(s,
1540                 "Registered: %d\r\n"
1541                 "NotRegistered: %d\r\n",
1542                 ami_outbound.registered,
1543                 ami_outbound.not_registered);
1544         astman_send_list_complete_end(s);
1545
1546         ao2_ref(regs, -1);
1547         return 0;
1548 }
1549
1550 static struct ao2_container *cli_get_container(void)
1551 {
1552         RAII_VAR(struct ao2_container *, container, get_registrations(), ao2_cleanup);
1553         struct ao2_container *s_container;
1554
1555         if (!container) {
1556                 return NULL;
1557         }
1558
1559         s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
1560                 ast_sorcery_object_id_sort, ast_sorcery_object_id_compare);
1561         if (!s_container) {
1562                 return NULL;
1563         }
1564
1565         if (ao2_container_dup(s_container, container, 0)) {
1566                 ao2_ref(s_container, -1);
1567                 return NULL;
1568         }
1569
1570         return s_container;
1571 }
1572
1573 static int cli_iterator(void *container, ao2_callback_fn callback, void *args)
1574 {
1575         ao2_callback(container, OBJ_NODATA, callback, args);
1576
1577         return 0;
1578 }
1579
1580 static void *cli_retrieve_by_id(const char *id)
1581 {
1582         struct ao2_container *states;
1583         void *obj = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration", id);
1584
1585         if (!obj) {
1586                 /* if the object no longer exists then remove its state  */
1587                 states = ao2_global_obj_ref(current_states);
1588                 if (states) {
1589                         ao2_find(states, id, OBJ_SEARCH_KEY | OBJ_UNLINK | OBJ_NODATA);
1590                         ao2_ref(states, -1);
1591                 }
1592         }
1593
1594         return obj;
1595 }
1596
1597 static int cli_print_header(void *obj, void *arg, int flags)
1598 {
1599         struct ast_sip_cli_context *context = arg;
1600
1601         ast_assert(context->output_buffer != NULL);
1602
1603         ast_str_append(&context->output_buffer, 0,
1604                 " <Registration/ServerURI..............................>  <Auth..........>  <Status.......>\n");
1605
1606         return 0;
1607 }
1608
1609 static int cli_print_body(void *obj, void *arg, int flags)
1610 {
1611         struct sip_outbound_registration *registration = obj;
1612         struct ast_sip_cli_context *context = arg;
1613         const char *id = ast_sorcery_object_get_id(registration);
1614         struct sip_outbound_registration_state *state = get_state(id);
1615 #define REGISTRATION_URI_FIELD_LEN      53
1616
1617         ast_assert(context->output_buffer != NULL);
1618
1619         if (!state) {
1620                 return 0;
1621         }
1622
1623         ast_str_append(&context->output_buffer, 0, " %-s/%-*.*s  %-16s  %-16s\n",
1624                 id,
1625                 (int) (REGISTRATION_URI_FIELD_LEN - strlen(id)),
1626                 (int) (REGISTRATION_URI_FIELD_LEN - strlen(id)),
1627                 registration->server_uri,
1628                 AST_VECTOR_SIZE(&registration->outbound_auths)
1629                         ? AST_VECTOR_GET(&registration->outbound_auths, 0)
1630                         : "n/a",
1631                 sip_outbound_registration_status_str[state->client_state->status]);
1632         ao2_ref(state, -1);
1633
1634         if (context->show_details
1635                 || (context->show_details_only_level_0 && context->indent_level == 0)) {
1636                 ast_str_append(&context->output_buffer, 0, "\n");
1637                 ast_sip_cli_print_sorcery_objectset(registration, context, 0);
1638         }
1639
1640         return 0;
1641 }
1642
1643 /*
1644  * A function pointer to callback needs to be within the
1645  * module in order to avoid problems with an undefined
1646  * symbol when the module is loaded.
1647  */
1648 static char *my_cli_traverse_objects(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1649 {
1650         return ast_sip_cli_traverse_objects(e, cmd, a);
1651 }
1652
1653 static struct ast_cli_entry cli_outbound_registration[] = {
1654         AST_CLI_DEFINE(cli_unregister, "Unregisters outbound registration target"),
1655         AST_CLI_DEFINE(cli_register, "Registers an outbound registration target"),
1656         AST_CLI_DEFINE(my_cli_traverse_objects, "List PJSIP Registrations",
1657                 .command = "pjsip list registrations",
1658                 .usage = "Usage: pjsip list registrations\n"
1659                                  "       List the configured PJSIP Registrations\n"),
1660         AST_CLI_DEFINE(my_cli_traverse_objects, "Show PJSIP Registrations",
1661                 .command = "pjsip show registrations",
1662                 .usage = "Usage: pjsip show registrations\n"
1663                                  "       Show the configured PJSIP Registrations\n"),
1664         AST_CLI_DEFINE(my_cli_traverse_objects, "Show PJSIP Registration",
1665                 .command = "pjsip show registration",
1666                 .usage = "Usage: pjsip show registration <id>\n"
1667                                  "       Show the configured PJSIP Registration\n"),
1668 };
1669
1670 static struct ast_sip_cli_formatter_entry *cli_formatter;
1671
1672 static void auth_observer(const char *type)
1673 {
1674         struct sip_outbound_registration *registration;
1675         struct sip_outbound_registration_state *state;
1676         struct ao2_container *regs;
1677         const char *registration_id;
1678         struct ao2_iterator i;
1679
1680         ast_debug(4, "Auths updated. Checking for any outbound registrations that are in permanent rejected state so they can be retried\n");
1681
1682         regs = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "registration",
1683                 AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
1684         if (!regs || ao2_container_count(regs) == 0) {
1685                 ao2_cleanup(regs);
1686                 return;
1687         }
1688
1689         i = ao2_iterator_init(regs, 0);
1690         for (; (registration = ao2_iterator_next(&i)); ao2_ref(registration, -1)) {
1691                 registration_id = ast_sorcery_object_get_id(registration);
1692                 state = get_state(registration_id);
1693                 if (state && state->client_state->status == SIP_REGISTRATION_REJECTED_PERMANENT) {
1694                         ast_debug(4, "Trying outbound registration '%s' again\n", registration_id);
1695
1696                         if (ast_sip_push_task(state->client_state->serializer,
1697                                               sip_outbound_registration_perform, ao2_bump(state))) {
1698                                 ast_log(LOG_ERROR, "Failed to perform outbound registration on '%s'\n", registration_id);
1699                                 ao2_ref(state, -1);
1700                         }
1701                 }
1702                 ao2_cleanup(state);
1703         }
1704         ao2_iterator_destroy(&i);
1705         ao2_cleanup(regs);
1706 }
1707
1708 static const struct ast_sorcery_observer observer_callbacks_auth = {
1709         .loaded = auth_observer,
1710 };
1711
1712 static int check_state(void *obj, void *arg, int flags)
1713 {
1714         struct sip_outbound_registration_state *state = obj;
1715         struct sip_outbound_registration *registration;
1716
1717         registration = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration",
1718                 ast_sorcery_object_get_id(state->registration));
1719         if (!registration) {
1720                 /* This is a dead registration */
1721                 return CMP_MATCH;
1722         }
1723
1724         ao2_ref(registration, -1);
1725         return 0;
1726 }
1727
1728 /*!
1729  * \internal
1730  * \brief Observer to purge dead registration states.
1731  *
1732  * \param name Module name owning the sorcery instance.
1733  * \param sorcery Instance being observed.
1734  * \param object_type Name of object being observed.
1735  * \param reloaded Non-zero if the object is being reloaded.
1736  *
1737  * \return Nothing
1738  */
1739 static void registration_loaded_observer(const char *name, const struct ast_sorcery *sorcery, const char *object_type, int reloaded)
1740 {
1741         struct ao2_container *states;
1742
1743         if (strcmp(object_type, "registration")) {
1744                 /* Not interested */
1745                 return;
1746         }
1747
1748         states = ao2_global_obj_ref(current_states);
1749         if (!states) {
1750                 /* Global container has gone.  Likely shutting down. */
1751                 return;
1752         }
1753
1754         /* Now to purge dead registrations. */
1755         ao2_callback(states, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, check_state, NULL);
1756         ao2_ref(states, -1);
1757 }
1758
1759 static const struct ast_sorcery_instance_observer observer_callbacks_registrations = {
1760         .object_type_loaded = registration_loaded_observer,
1761 };
1762
1763 static int unload_module(void)
1764 {
1765         ast_sip_unregister_endpoint_identifier(&line_identifier);
1766         ast_sorcery_observer_remove(ast_sip_get_sorcery(), "auth", &observer_callbacks_auth);
1767         ast_sorcery_instance_observer_remove(ast_sip_get_sorcery(), &observer_callbacks_registrations);
1768         ast_cli_unregister_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration));
1769         ast_sip_unregister_cli_formatter(cli_formatter);
1770         ast_manager_unregister("PJSIPShowRegistrationsOutbound");
1771         ast_manager_unregister("PJSIPUnregister");
1772         ast_manager_unregister("PJSIPRegister");
1773
1774         ao2_global_obj_release(current_states);
1775
1776         return 0;
1777 }
1778
1779 static int load_module(void)
1780 {
1781         struct ao2_container *new_states;
1782
1783         CHECK_PJSIP_MODULE_LOADED();
1784
1785         ast_sorcery_apply_config(ast_sip_get_sorcery(), "res_pjsip_outbound_registration");
1786         ast_sorcery_apply_default(ast_sip_get_sorcery(), "registration", "config", "pjsip.conf,criteria=type=registration");
1787
1788         if (ast_sorcery_object_register(ast_sip_get_sorcery(), "registration", sip_outbound_registration_alloc, NULL, sip_outbound_registration_apply)) {
1789                 return AST_MODULE_LOAD_DECLINE;
1790         }
1791
1792         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "type", "", OPT_NOOP_T, 0, 0);
1793         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "server_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, server_uri));
1794         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "client_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, client_uri));
1795         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "contact_user", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, contact_user));
1796         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, transport));
1797         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, outbound_proxy));
1798         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "expiration", "3600", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, expiration));
1799         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "retry_interval", "60", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, retry_interval));
1800         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));
1801         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "max_retries", "10", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, max_retries));
1802         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));
1803         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);
1804         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "support_path", "no", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, support_path));
1805         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "line", "no", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, line));
1806         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "endpoint", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, endpoint));
1807         ast_sip_register_endpoint_identifier(&line_identifier);
1808
1809         ast_manager_register_xml("PJSIPUnregister", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_unregister);
1810         ast_manager_register_xml("PJSIPRegister", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_register);
1811         ast_manager_register_xml("PJSIPShowRegistrationsOutbound", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_show_outbound_registrations);
1812
1813         cli_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
1814         if (!cli_formatter) {
1815                 ast_log(LOG_ERROR, "Unable to allocate memory for cli formatter\n");
1816                 unload_module();
1817                 return AST_MODULE_LOAD_FAILURE;
1818         }
1819         cli_formatter->name = "registration";
1820         cli_formatter->print_header = cli_print_header;
1821         cli_formatter->print_body = cli_print_body;
1822         cli_formatter->get_container = cli_get_container;
1823         cli_formatter->iterate = cli_iterator;
1824         cli_formatter->get_id = ast_sorcery_object_get_id;
1825         cli_formatter->retrieve_by_id = cli_retrieve_by_id;
1826
1827         ast_sip_register_cli_formatter(cli_formatter);
1828         ast_cli_register_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration));
1829
1830         new_states = ao2_container_alloc(DEFAULT_STATE_BUCKETS,
1831                 registration_state_hash, registration_state_cmp);
1832         if (!new_states) {
1833                 ast_log(LOG_ERROR, "Unable to allocate registration states container\n");
1834                 unload_module();
1835                 return AST_MODULE_LOAD_FAILURE;
1836         }
1837         ao2_global_obj_replace_unref(current_states, new_states);
1838         ao2_ref(new_states, -1);
1839
1840         if (ast_sorcery_instance_observer_add(ast_sip_get_sorcery(),
1841                 &observer_callbacks_registrations)) {
1842                 unload_module();
1843                 return AST_MODULE_LOAD_FAILURE;
1844         }
1845
1846         ast_sorcery_load_object(ast_sip_get_sorcery(), "registration");
1847
1848         ast_sorcery_observer_add(ast_sip_get_sorcery(), "auth", &observer_callbacks_auth);
1849
1850         return AST_MODULE_LOAD_SUCCESS;
1851 }
1852
1853 static int reload_module(void)
1854 {
1855         ast_sorcery_reload_object(ast_sip_get_sorcery(), "registration");
1856         return 0;
1857 }
1858
1859 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Outbound Registration Support",
1860         .support_level = AST_MODULE_SUPPORT_CORE,
1861         .load = load_module,
1862         .reload = reload_module,
1863         .unload = unload_module,
1864         .load_pri = AST_MODPRI_APP_DEPEND,
1865 );