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