Debug messages for pjsip outbound registration
[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/module.h"
32 #include "asterisk/taskprocessor.h"
33 #include "asterisk/cli.h"
34 #include "asterisk/stasis_system.h"
35
36 /*** DOCUMENTATION
37         <configInfo name="res_pjsip_outbound_registration" language="en_US">
38                 <synopsis>SIP resource for outbound registrations</synopsis>
39                 <description><para>
40                         <emphasis>Outbound Registration</emphasis>
41                         </para>
42                         <para>This module allows <literal>res_pjsip</literal> to register to other SIP servers.</para>
43                 </description>
44                 <configFile name="pjsip.conf">
45                         <configObject name="registration">
46                                 <synopsis>The configuration for outbound registration</synopsis>
47                                 <description><para>
48                                         Registration is <emphasis>COMPLETELY</emphasis> separate from the rest of
49                                         <literal>pjsip.conf</literal>. A minimal configuration consists of
50                                         setting a <literal>server_uri</literal> and a <literal>client_uri</literal>.
51                                 </para></description>
52                                 <configOption name="auth_rejection_permanent" default="yes">
53                                         <synopsis>Determines whether failed authentication challenges are treated
54                                         as permanent failures.</synopsis>
55                                         <description><para>If this option is enabled and an authentication challenge fails,
56                                         registration will not be attempted again until the configuration is reloaded.</para></description>
57                                 </configOption>
58                                 <configOption name="client_uri">
59                                         <synopsis>Client SIP URI used when attemping outbound registration</synopsis>
60                                 </configOption>
61                                 <configOption name="contact_user">
62                                         <synopsis>Contact User to use in request</synopsis>
63                                 </configOption>
64                                 <configOption name="expiration" default="3600">
65                                         <synopsis>Expiration time for registrations in seconds</synopsis>
66                                 </configOption>
67                                 <configOption name="max_retries" default="10">
68                                         <synopsis>Maximum number of registration attempts.</synopsis>
69                                 </configOption>
70                                 <configOption name="outbound_auth" default="">
71                                         <synopsis>Authentication object to be used for outbound registrations.</synopsis>
72                                 </configOption>
73                                 <configOption name="outbound_proxy" default="">
74                                         <synopsis>Outbound Proxy used to send registrations</synopsis>
75                                 </configOption>
76                                 <configOption name="retry_interval" default="60">
77                                         <synopsis>Interval in seconds between retries if outbound registration is unsuccessful</synopsis>
78                                 </configOption>
79                                 <configOption name="server_uri">
80                                         <synopsis>SIP URI of the server to register against</synopsis>
81                                 </configOption>
82                                 <configOption name="transport">
83                                         <synopsis>Transport used for outbound authentication</synopsis>
84                                         <description>
85                                                 <note><para>A <replaceable>transport</replaceable> configured in
86                                                 <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>
87                                         </description>
88                                 </configOption>
89                                 <configOption name="type">
90                                         <synopsis>Must be of type 'registration'.</synopsis>
91                                 </configOption>
92                         </configObject>
93                 </configFile>
94         </configInfo>
95         <manager name="PJSIPUnregister" language="en_US">
96                 <synopsis>
97                         Unregister an outbound registration.
98                 </synopsis>
99                 <syntax>
100                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
101                         <parameter name="Registration" required="true">
102                                 <para>The outbound registration to unregister.</para>
103                         </parameter>
104                 </syntax>
105         </manager>
106  ***/
107
108 /*! \brief Amount of buffer time (in seconds) before expiration that we re-register at */
109 #define REREGISTER_BUFFER_TIME 10
110
111 /*! \brief Various states that an outbound registration may be in */
112 enum sip_outbound_registration_status {
113         /*! \brief Currently unregistered */
114         SIP_REGISTRATION_UNREGISTERED = 0,
115         /*! \brief Registered, yay! */
116         SIP_REGISTRATION_REGISTERED,
117         /*! \brief Registration was rejected, but response was temporal */
118         SIP_REGISTRATION_REJECTED_TEMPORARY,
119         /*! \brief Registration was rejected, permanently */
120         SIP_REGISTRATION_REJECTED_PERMANENT,
121         /*! \brief Registration has been stopped */
122         SIP_REGISTRATION_STOPPED,
123 };
124
125 static const char *sip_outbound_registration_status_str[] = {
126         [SIP_REGISTRATION_UNREGISTERED] = "Unregistered",
127         [SIP_REGISTRATION_REGISTERED] = "Registered",
128         [SIP_REGISTRATION_REJECTED_TEMPORARY] = "Rejected",
129         [SIP_REGISTRATION_REJECTED_PERMANENT] = "Rejected",
130         [SIP_REGISTRATION_STOPPED] = "Stopped",
131 };
132
133 /*! \brief Outbound registration client state information (persists for lifetime of regc) */
134 struct sip_outbound_registration_client_state {
135         /*! \brief Current status of this registration */
136         enum sip_outbound_registration_status status;
137         /*! \brief Outbound registration client */
138         pjsip_regc *client;
139         /*! \brief Timer entry for retrying on temporal responses */
140         pj_timer_entry timer;
141         /*! \brief Current number of retries */
142         unsigned int retries;
143         /*! \brief Maximum number of retries permitted */
144         unsigned int max_retries;
145         /*! \brief Interval at which retries should occur for temporal responses */
146         unsigned int retry_interval;
147         /*! \brief Treat authentication challenges that we cannot handle as permanent failures */
148         unsigned int auth_rejection_permanent;
149         /*! \brief Serializer for stuff and things */
150         struct ast_taskprocessor *serializer;
151         /*! \brief Configured authentication credentials */
152         struct ast_sip_auth_array outbound_auths;
153         /*! \brief Number of configured auths */
154         size_t num_outbound_auths;
155         /*! \brief Registration should be destroyed after completion of transaction */
156         unsigned int destroy:1;
157 };
158
159 /*! \brief Outbound registration state information (persists for lifetime that registration should exist) */
160 struct sip_outbound_registration_state {
161         /*! \brief Client state information */
162         struct sip_outbound_registration_client_state *client_state;
163 };
164
165 /*! \brief Outbound registration information */
166 struct sip_outbound_registration {
167         /*! \brief Sorcery object details */
168         SORCERY_OBJECT(details);
169         /*! \brief Stringfields */
170         AST_DECLARE_STRING_FIELDS(
171                 /*! \brief URI for the registrar */
172                 AST_STRING_FIELD(server_uri);
173                 /*! \brief URI for the AOR */
174                 AST_STRING_FIELD(client_uri);
175                 /*! \brief Optional user for contact header */
176                 AST_STRING_FIELD(contact_user);
177                 /*! \brief Explicit transport to use for registration */
178                 AST_STRING_FIELD(transport);
179                 /*! \brief Outbound proxy to use */
180                 AST_STRING_FIELD(outbound_proxy);
181         );
182         /*! \brief Requested expiration time */
183         unsigned int expiration;
184         /*! \brief Interval at which retries should occur for temporal responses */
185         unsigned int retry_interval;
186         /*! \brief Treat authentication challenges that we cannot handle as permanent failures */
187         unsigned int auth_rejection_permanent;
188         /*! \brief Maximum number of retries permitted */
189         unsigned int max_retries;
190         /*! \brief Outbound registration state */
191         struct sip_outbound_registration_state *state;
192         /*! \brief Configured authentication credentials */
193         struct ast_sip_auth_array outbound_auths;
194         /*! \brief Number of configured auths */
195         size_t num_outbound_auths;
196 };
197
198 /*! \brief Helper function which cancels the timer on a client */
199 static void cancel_registration(struct sip_outbound_registration_client_state *client_state)
200 {
201         if (pj_timer_heap_cancel(pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()), &client_state->timer)) {
202                 /* The timer was successfully cancelled, drop the refcount of client_state */
203                 ao2_ref(client_state, -1);
204         }
205 }
206
207 /*! \brief Callback function for registering */
208 static int handle_client_registration(void *data)
209 {
210         RAII_VAR(struct sip_outbound_registration_client_state *, client_state, data, ao2_cleanup);
211         pjsip_tx_data *tdata;
212         pjsip_regc_info info;
213         char server_uri[PJSIP_MAX_URL_SIZE], client_uri[PJSIP_MAX_URL_SIZE];
214
215         cancel_registration(client_state);
216
217         if ((client_state->status == SIP_REGISTRATION_STOPPED) ||
218                 (pjsip_regc_register(client_state->client, PJ_FALSE, &tdata) != PJ_SUCCESS)) {
219                 return 0;
220         }
221
222         pjsip_regc_get_info(client_state->client, &info);
223         ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
224         ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
225         ast_debug(3, "REGISTER attempt %d to '%s' with client '%s'\n",
226                   client_state->retries + 1, server_uri, client_uri);
227
228         /* Due to the registration the callback may now get called, so bump the ref count */
229         ao2_ref(client_state, +1);
230         if (pjsip_regc_send(client_state->client, tdata) != PJ_SUCCESS) {
231                 ao2_ref(client_state, -1);
232         }
233
234         return 0;
235 }
236
237 /*! \brief Timer callback function, used just for registrations */
238 static void sip_outbound_registration_timer_cb(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
239 {
240         struct sip_outbound_registration_client_state *client_state = entry->user_data;
241
242         ao2_ref(client_state, +1);
243         if (ast_sip_push_task(client_state->serializer, handle_client_registration, client_state)) {
244                 ast_log(LOG_WARNING, "Failed to pass outbound registration to threadpool\n");
245                 ao2_ref(client_state, -1);
246         }
247
248         entry->id = 0;
249 }
250
251 /*! \brief Helper function which sets up the timer to re-register in a specific amount of time */
252 static void schedule_registration(struct sip_outbound_registration_client_state *client_state, unsigned int seconds)
253 {
254         pj_time_val delay = { .sec = seconds, };
255
256         cancel_registration(client_state);
257
258         ao2_ref(client_state, +1);
259         if (pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(), &client_state->timer, &delay) != PJ_SUCCESS) {
260                 ast_log(LOG_WARNING, "Failed to pass timed registration to scheduler\n");
261                 ao2_ref(client_state, -1);
262         }
263 }
264
265 /*! \brief Callback function for unregistering (potentially) and destroying state */
266 static int handle_client_state_destruction(void *data)
267 {
268         RAII_VAR(struct sip_outbound_registration_client_state *, client_state, data, ao2_cleanup);
269         pjsip_regc_info info;
270
271         cancel_registration(client_state);
272
273         pjsip_regc_get_info(client_state->client, &info);
274
275         if (info.is_busy == PJ_TRUE) {
276                 /* If a client transaction is in progress we defer until it is complete */
277                 client_state->destroy = 1;
278                 return 0;
279         }
280
281         if (client_state->status != SIP_REGISTRATION_UNREGISTERED && client_state->status != SIP_REGISTRATION_REJECTED_PERMANENT) {
282                 pjsip_tx_data *tdata;
283
284                 if (pjsip_regc_unregister(client_state->client, &tdata) == PJ_SUCCESS) {
285                         pjsip_regc_send(client_state->client, tdata);
286                 }
287         }
288
289         pjsip_regc_destroy(client_state->client);
290
291         client_state->status = SIP_REGISTRATION_STOPPED;
292         ast_sip_auth_array_destroy(&client_state->outbound_auths);
293
294         return 0;
295 }
296
297 /*! \brief Structure for registration response */
298 struct registration_response {
299         /*! \brief Response code for the registration attempt */
300         int code;
301         /*! \brief Expiration time for registration */
302         int expiration;
303         /*! \brief Retry-After value */
304         int retry_after;
305         /*! \brief Outbound registration client state */
306         struct sip_outbound_registration_client_state *client_state;
307         /*! \brief The response message */
308         pjsip_rx_data *rdata;
309         /*! \brief The response transaction */
310         pjsip_transaction *tsx;
311 };
312
313 /*! \brief Registration response structure destructor */
314 static void registration_response_destroy(void *obj)
315 {
316         struct registration_response *response = obj;
317
318         if (response->rdata) {
319                 pjsip_rx_data_free_cloned(response->rdata);
320         }
321
322         ao2_cleanup(response->client_state);
323 }
324
325 /* \brief Helper funtion which determines if a response code is temporal or not */
326 static int sip_outbound_registration_is_temporal(unsigned int code,
327                 struct sip_outbound_registration_client_state *client_state)
328 {
329         /* Shamelessly taken from pjsua */
330         if (code == PJSIP_SC_REQUEST_TIMEOUT ||
331                 code == PJSIP_SC_INTERNAL_SERVER_ERROR ||
332                 code == PJSIP_SC_BAD_GATEWAY ||
333                 code == PJSIP_SC_SERVICE_UNAVAILABLE ||
334                 code == PJSIP_SC_SERVER_TIMEOUT ||
335                 ((code == PJSIP_SC_UNAUTHORIZED ||
336                   code == PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED) &&
337                  !client_state->auth_rejection_permanent) ||
338                 PJSIP_IS_STATUS_IN_CLASS(code, 600)) {
339                 return 1;
340         } else {
341                 return 0;
342         }
343 }
344
345 /*! \brief Callback function for handling a response to a registration attempt */
346 static int handle_registration_response(void *data)
347 {
348         RAII_VAR(struct registration_response *, response, data, ao2_cleanup);
349         pjsip_regc_info info;
350         char server_uri[PJSIP_MAX_URL_SIZE], client_uri[PJSIP_MAX_URL_SIZE];
351
352         if (response->client_state->status == SIP_REGISTRATION_STOPPED) {
353                 return 0;
354         }
355
356         pjsip_regc_get_info(response->client_state->client, &info);
357         ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
358         ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
359
360         if (response->code == 401 || response->code == 407) {
361                 pjsip_tx_data *tdata;
362                 if (!ast_sip_create_request_with_auth(&response->client_state->outbound_auths,
363                                 response->rdata, response->tsx, &tdata)) {
364                         ao2_ref(response->client_state, +1);
365                         if (pjsip_regc_send(response->client_state->client, tdata) != PJ_SUCCESS) {
366                                 ao2_cleanup(response->client_state);
367                         }
368                         return 0;
369                 }
370                 /* Otherwise, fall through so the failure is processed appropriately */
371         }
372
373         if (PJSIP_IS_STATUS_IN_CLASS(response->code, 200)) {
374                 /* If the registration went fine simply reschedule registration for the future */
375                 ast_debug(1, "Outbound registration to '%s' with client '%s' successful\n", server_uri, client_uri);
376                 response->client_state->status = SIP_REGISTRATION_REGISTERED;
377                 response->client_state->retries = 0;
378                 schedule_registration(response->client_state, response->expiration - REREGISTER_BUFFER_TIME);
379         } else if (response->retry_after) {
380                 /* If we have been instructed to retry after a period of time, schedule it as such */
381                 response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY;
382                 schedule_registration(response->client_state, response->retry_after);
383                 ast_log(LOG_WARNING, "Temporal response '%d' received from '%s' on registration attempt to '%s', instructed to retry in '%d'\n",
384                         response->code, server_uri, client_uri, response->retry_after);
385         } else if (response->client_state->retry_interval && sip_outbound_registration_is_temporal(response->code, response->client_state)) {
386                 if (response->client_state->retries == response->client_state->max_retries) {
387                         /* If we received enough temporal responses to exceed our maximum give up permanently */
388                         response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT;
389                         ast_log(LOG_WARNING, "Maximum retries reached when attempting outbound registration to '%s' with client '%s', stopping registration attempt\n",
390                                 server_uri, client_uri);
391                 } else {
392                         /* On the other hand if we can still try some more do so */
393                         response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY;
394                         response->client_state->retries++;
395                         schedule_registration(response->client_state, response->client_state->retry_interval);
396                         ast_log(LOG_WARNING, "Temporal response '%d' received from '%s' on registration attempt to '%s', retrying in '%d' seconds\n",
397                                 response->code, server_uri, client_uri, response->client_state->retry_interval);
398                 }
399         } else {
400                 /* Finally if there's no hope of registering give up */
401                 response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT;
402                 ast_log(LOG_WARNING, "Fatal response '%d' received from '%s' on registration attempt to '%s', stopping outbound registration\n",
403                         response->code, server_uri, client_uri);
404         }
405
406         ast_system_publish_registry("PJSIP", client_uri, server_uri, sip_outbound_registration_status_str[response->client_state->status], NULL);
407
408         /* If deferred destruction is in use see if we need to destroy now */
409         if (response->client_state->destroy) {
410                 handle_client_state_destruction(response->client_state);
411         }
412
413         return 0;
414 }
415
416 /*! \brief Callback function for outbound registration client */
417 static void sip_outbound_registration_response_cb(struct pjsip_regc_cbparam *param)
418 {
419         RAII_VAR(struct sip_outbound_registration_client_state *, client_state, param->token, ao2_cleanup);
420         struct registration_response *response = ao2_alloc(sizeof(*response), registration_response_destroy);
421
422         response->code = param->code;
423         response->expiration = param->expiration;
424         response->client_state = client_state;
425         ao2_ref(response->client_state, +1);
426
427         if (param->rdata) {
428                 struct pjsip_retry_after_hdr *retry_after = pjsip_msg_find_hdr(param->rdata->msg_info.msg, PJSIP_H_RETRY_AFTER, NULL);
429
430                 response->retry_after = retry_after ? retry_after->ivalue : 0;
431                 response->tsx = pjsip_rdata_get_tsx(param->rdata);
432                 pjsip_rx_data_clone(param->rdata, 0, &response->rdata);
433         }
434
435         if (ast_sip_push_task(client_state->serializer, handle_registration_response, response)) {
436                 ast_log(LOG_WARNING, "Failed to pass incoming registration response to threadpool\n");
437                 ao2_cleanup(response);
438         }
439 }
440
441 /*! \brief Destructor function for registration state */
442 static void sip_outbound_registration_state_destroy(void *obj)
443 {
444         struct sip_outbound_registration_state *state = obj;
445
446         if (!state->client_state) {
447                 return;
448         }
449
450         if (state->client_state->serializer && ast_sip_push_task(state->client_state->serializer, handle_client_state_destruction, state->client_state)) {
451                 ast_log(LOG_WARNING, "Failed to pass outbound registration client destruction to threadpool\n");
452                 ao2_ref(state->client_state, -1);
453         }
454 }
455
456 /*! \brief Destructor function for client registration state */
457 static void sip_outbound_registration_client_state_destroy(void *obj)
458 {
459         struct sip_outbound_registration_client_state *client_state = obj;
460
461         ast_taskprocessor_unreference(client_state->serializer);
462 }
463
464 /*! \brief Allocator function for registration state */
465 static struct sip_outbound_registration_state *sip_outbound_registration_state_alloc(void)
466 {
467         struct sip_outbound_registration_state *state = ao2_alloc(sizeof(*state), sip_outbound_registration_state_destroy);
468
469         if (!state || !(state->client_state = ao2_alloc(sizeof(*state->client_state), sip_outbound_registration_client_state_destroy))) {
470                 ao2_cleanup(state);
471                 return NULL;
472         }
473
474         if ((pjsip_regc_create(ast_sip_get_pjsip_endpoint(), state->client_state, sip_outbound_registration_response_cb, &state->client_state->client) != PJ_SUCCESS) ||
475                 !(state->client_state->serializer = ast_sip_create_serializer())) {
476                 /* This is on purpose, normal operation will have it be deallocated within the serializer */
477                 pjsip_regc_destroy(state->client_state->client);
478                 ao2_cleanup(state->client_state);
479                 ao2_cleanup(state);
480                 return NULL;
481         }
482
483         state->client_state->status = SIP_REGISTRATION_UNREGISTERED;
484         state->client_state->timer.user_data = state->client_state;
485         state->client_state->timer.cb = sip_outbound_registration_timer_cb;
486
487         return state;
488 }
489
490 /*! \brief Destructor function for registration information */
491 static void sip_outbound_registration_destroy(void *obj)
492 {
493         struct sip_outbound_registration *registration = obj;
494
495         ao2_cleanup(registration->state);
496         ast_sip_auth_array_destroy(&registration->outbound_auths);
497
498         ast_string_field_free_memory(registration);
499 }
500
501 /*! \brief Allocator function for registration information */
502 static void *sip_outbound_registration_alloc(const char *name)
503 {
504         struct sip_outbound_registration *registration = ast_sorcery_generic_alloc(sizeof(*registration), sip_outbound_registration_destroy);
505
506         if (!registration || ast_string_field_init(registration, 256)) {
507                 ao2_cleanup(registration);
508                 return NULL;
509         }
510
511         return registration;
512 }
513
514 /*! \brief Helper function which populates a pj_str_t with a contact header */
515 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)
516 {
517         pj_str_t tmp, local_addr;
518         pjsip_uri *uri;
519         pjsip_sip_uri *sip_uri;
520         pjsip_transport_type_e type = PJSIP_TRANSPORT_UNSPECIFIED;
521         int local_port;
522
523         pj_strdup_with_null(pool, &tmp, target);
524
525         if (!(uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0)) ||
526             (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
527                 return -1;
528         }
529
530         sip_uri = pjsip_uri_get_uri(uri);
531
532         if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
533                 type = PJSIP_TRANSPORT_TLS;
534         } else if (!sip_uri->transport_param.slen) {
535                 type = PJSIP_TRANSPORT_UDP;
536         } else {
537                 type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
538         }
539
540         if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
541                 return -1;
542         }
543
544         if (pj_strchr(&sip_uri->host, ':')) {
545                 type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
546         }
547
548         if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), pool, type, selector,
549                                                               &local_addr, &local_port) != PJ_SUCCESS) {
550                 return -1;
551         }
552
553         if (!pj_strchr(&sip_uri->host, ':') && pj_strchr(&local_addr, ':')) {
554                 type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
555         }
556
557         contact->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
558         contact->slen = pj_ansi_snprintf(contact->ptr, PJSIP_MAX_URL_SIZE,
559                                       "<%s:%s@%s%.*s%s:%d%s%s>",
560                                       (pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE) ? "sips" : "sip",
561                                       user,
562                                       (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
563                                       (int)local_addr.slen,
564                                       local_addr.ptr,
565                                       (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
566                                       local_port,
567                                       (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
568                                       (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
569
570         return 0;
571 }
572
573 /*!
574  * \internal
575  * \brief Check if a registration can be reused
576  *
577  * This checks if the existing outbound registration's configuration differs from a newly-applied
578  * outbound registration to see if the applied one.
579  *
580  * \param existing The pre-existing outbound registration
581  * \param applied The newly-created registration
582  */
583 static int can_reuse_registration(struct sip_outbound_registration *existing, struct sip_outbound_registration *applied)
584 {
585         int i;
586
587         if (strcmp(existing->server_uri, applied->server_uri) || strcmp(existing->client_uri, applied->client_uri) ||
588                 strcmp(existing->transport, applied->transport) || strcmp(existing->contact_user, applied->contact_user) ||
589                 strcmp(existing->outbound_proxy, applied->outbound_proxy) || existing->num_outbound_auths != applied->num_outbound_auths ||
590                 existing->auth_rejection_permanent != applied->auth_rejection_permanent) {
591                 return 0;
592         }
593
594         for (i = 0; i < existing->num_outbound_auths; ++i) {
595                 if (strcmp(existing->outbound_auths.names[i], applied->outbound_auths.names[i])) {
596                         return 0;
597                 }
598         }
599
600         return 1;
601 }
602
603 /*! \brief Helper function that allocates a pjsip registration client and configures it */
604 static int sip_outbound_registration_regc_alloc(void *data)
605 {
606         struct sip_outbound_registration *registration = data;
607         pj_str_t server_uri, client_uri, contact_uri;
608         pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
609
610         if (!ast_strlen_zero(registration->transport)) {
611                 RAII_VAR(struct ast_sip_transport *, transport, ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", registration->transport), ao2_cleanup);
612
613                 if (!transport || !transport->state) {
614                         ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport '%s' "
615                                 " for outbound registration", registration->transport);
616                         return -1;
617                 }
618
619                 if (transport->state->transport) {
620                         selector.type = PJSIP_TPSELECTOR_TRANSPORT;
621                         selector.u.transport = transport->state->transport;
622                 } else if (transport->state->factory) {
623                         selector.type = PJSIP_TPSELECTOR_LISTENER;
624                         selector.u.listener = transport->state->factory;
625                 } else {
626                         return -1;
627                 }
628         }
629
630         pjsip_regc_set_transport(registration->state->client_state->client, &selector);
631
632         if (!ast_strlen_zero(registration->outbound_proxy)) {
633                 pjsip_route_hdr route_set, *route;
634                 static const pj_str_t ROUTE_HNAME = { "Route", 5 };
635                 pj_str_t tmp;
636
637                 pj_list_init(&route_set);
638
639                 pj_strdup2_with_null(pjsip_regc_get_pool(registration->state->client_state->client), &tmp, registration->outbound_proxy);
640                 if (!(route = pjsip_parse_hdr(pjsip_regc_get_pool(registration->state->client_state->client), &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
641                         return -1;
642                 }
643                 pj_list_push_back(&route_set, route);
644
645                 pjsip_regc_set_route_set(registration->state->client_state->client, &route_set);
646         }
647
648         pj_cstr(&server_uri, registration->server_uri);
649
650         if (sip_dialog_create_contact(pjsip_regc_get_pool(registration->state->client_state->client), &contact_uri, S_OR(registration->contact_user, "s"), &server_uri, &selector)) {
651                 return -1;
652         }
653
654         pj_cstr(&client_uri, registration->client_uri);
655
656         if (pjsip_regc_init(registration->state->client_state->client, &server_uri, &client_uri, &client_uri, 1, &contact_uri, registration->expiration) != PJ_SUCCESS) {
657                 return -1;
658         }
659
660         return 0;
661 }
662
663 /*! \brief Apply function which finds or allocates a state structure */
664 static int sip_outbound_registration_apply(const struct ast_sorcery *sorcery, void *obj)
665 {
666         RAII_VAR(struct sip_outbound_registration *, existing, ast_sorcery_retrieve_by_id(sorcery, "registration", ast_sorcery_object_get_id(obj)), ao2_cleanup);
667         struct sip_outbound_registration *applied = obj;
668
669         if (!existing) {
670                 /* If no existing registration exists we can just start fresh easily */
671                 applied->state = sip_outbound_registration_state_alloc();
672         } else {
673                 /* If there is an existing registration things are more complicated, we can immediately reuse this state if most stuff remains unchanged */
674                 if (can_reuse_registration(existing, applied)) {
675                         applied->state = existing->state;
676                         ao2_ref(applied->state, +1);
677                         return 0;
678                 }
679                 applied->state = sip_outbound_registration_state_alloc();
680         }
681
682         if (!applied->state) {
683                 return -1;
684         }
685
686         return ast_sip_push_task_synchronous(NULL, sip_outbound_registration_regc_alloc, applied);
687 }
688
689 /*! \brief Helper function which performs a single registration */
690 static int sip_outbound_registration_perform(void *data)
691 {
692         RAII_VAR(struct sip_outbound_registration *, registration, data, ao2_cleanup);
693         size_t i;
694
695         /* Just in case the client state is being reused for this registration, free the auth information */
696         ast_sip_auth_array_destroy(&registration->state->client_state->outbound_auths);
697
698         registration->state->client_state->outbound_auths.names = ast_calloc(registration->outbound_auths.num, sizeof(char *));
699         for (i = 0; i < registration->outbound_auths.num; ++i) {
700                 registration->state->client_state->outbound_auths.names[i] = ast_strdup(registration->outbound_auths.names[i]);
701         }
702         registration->state->client_state->outbound_auths.num = registration->outbound_auths.num;
703         registration->state->client_state->retry_interval = registration->retry_interval;
704         registration->state->client_state->max_retries = registration->max_retries;
705         registration->state->client_state->retries = 0;
706
707         pjsip_regc_update_expires(registration->state->client_state->client, registration->expiration);
708
709         schedule_registration(registration->state->client_state, (ast_random() % 10) + 1);
710
711         return 0;
712 }
713
714 /*! \brief Helper function which performs all registrations */
715 static void sip_outbound_registration_perform_all(void)
716 {
717         RAII_VAR(struct ao2_container *, registrations, ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "registration", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL), ao2_cleanup);
718         struct ao2_iterator i;
719         struct sip_outbound_registration *registration;
720
721         if (!registrations) {
722                 return;
723         }
724
725         i = ao2_iterator_init(registrations, 0);
726         while ((registration = ao2_iterator_next(&i))) {
727                 if (ast_sip_push_task(registration->state->client_state->serializer, sip_outbound_registration_perform, registration)) {
728                         ast_log(LOG_ERROR, "Failed to perform outbound registration on '%s'\n", ast_sorcery_object_get_id(registration));
729                         ao2_ref(registration, -1);
730                 }
731         }
732         ao2_iterator_destroy(&i);
733 }
734
735 static int outbound_auth_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
736 {
737         struct sip_outbound_registration *registration = obj;
738
739         return ast_sip_auth_array_init(&registration->outbound_auths, var->value);
740 }
741
742 static struct sip_outbound_registration *retrieve_registration(const char *registration_name)
743 {
744         return ast_sorcery_retrieve_by_id(
745                 ast_sip_get_sorcery(),
746                 "registration",
747                 registration_name);
748 }
749
750 static int unregister_task(void *obj)
751 {
752         RAII_VAR(struct sip_outbound_registration*, registration, obj, ao2_cleanup);
753         struct pjsip_regc *client = registration->state->client_state->client;
754         pjsip_tx_data *tdata;
755
756         if (pjsip_regc_unregister(client, &tdata) != PJ_SUCCESS) {
757                 return 0;
758         }
759
760         ao2_ref(registration->state->client_state, +1);
761         if (pjsip_regc_send(client, tdata) != PJ_SUCCESS) {
762                 ao2_cleanup(registration->state->client_state);
763         }
764
765         return 0;
766 }
767
768 static int queue_unregister(struct sip_outbound_registration *registration)
769 {
770         ao2_ref(registration, +1);
771         if (ast_sip_push_task(registration->state->client_state->serializer, unregister_task, registration)) {
772                 ao2_cleanup(registration);
773                 return -1;
774         }
775         return 0;
776 }
777
778 static char *cli_complete_registration(const char *line, const char *word,
779 int pos, int state)
780 {
781         char *result = NULL;
782         int wordlen;
783         int which = 0;
784         struct sip_outbound_registration *registration;
785         RAII_VAR(struct ao2_container *, registrations, NULL, ao2_cleanup);
786         struct ao2_iterator i;
787
788         if (pos != 3) {
789                 return NULL;
790         }
791
792         wordlen = strlen(word);
793         registrations = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "registration",
794                 AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
795         if (!registrations) {
796                 return NULL;
797         }
798
799         i = ao2_iterator_init(registrations, 0);
800         while ((registration = ao2_iterator_next(&i))) {
801                 const char *name = ast_sorcery_object_get_id(registration);
802                 if (!strncasecmp(word, name, wordlen) && ++which > state) {
803                         result = ast_strdup(name);
804                 }
805
806                 ao2_cleanup(registration);
807                 if (result) {
808                         break;
809                 }
810         }
811         ao2_iterator_destroy(&i);
812         return result;
813 }
814
815 static char *cli_unregister(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
816 {
817         RAII_VAR(struct sip_outbound_registration *, registration, NULL, ao2_cleanup);
818         const char *registration_name;
819
820         switch (cmd) {
821         case CLI_INIT:
822                 e->command = "pjsip send unregister";
823                 e->usage =
824                         "Usage: pjsip send unregister <registration>\n"
825                         "       Send a SIP REGISTER request to the specified outbound "
826                         "registration with an expiration of 0. This will cause the contact "
827                         "added by this registration to be removed on the remote system.\n";
828                 return NULL;
829         case CLI_GENERATE:
830                 return cli_complete_registration(a->line, a->word, a->pos, a->n);
831         }
832
833         if (a->argc != 4) {
834                 return CLI_SHOWUSAGE;
835         }
836
837         registration_name = a->argv[3];
838
839         registration = retrieve_registration(registration_name);
840         if (!registration) {
841                 ast_cli(a->fd, "Unable to retrieve registration %s\n", registration_name);
842                 return CLI_FAILURE;
843         }
844
845         if (queue_unregister(registration)) {
846                 ast_cli(a->fd, "Failed to queue unregistration");
847                 return 0;
848         }
849
850         return CLI_SUCCESS;
851 }
852
853 static int ami_unregister(struct mansession *s, const struct message *m)
854 {
855         const char *registration_name = astman_get_header(m, "Registration");
856         RAII_VAR(struct sip_outbound_registration *, registration, NULL, ao2_cleanup);
857
858         if (ast_strlen_zero(registration_name)) {
859                 astman_send_error(s, m, "Registration parameter missing.");
860                 return 0;
861         }
862
863         registration = retrieve_registration(registration_name);
864         if (!registration) {
865                 astman_send_error(s, m, "Unable to retrieve registration entry\n");
866                 return 0;
867         }
868
869
870         if (queue_unregister(registration)) {
871                 astman_send_ack(s, m, "Failed to queue unregistration");
872                 return 0;
873         }
874
875         astman_send_ack(s, m, "Unregistration sent");
876         return 0;
877 }
878
879 static struct ast_cli_entry cli_outbound_registration[] = {
880         AST_CLI_DEFINE(cli_unregister, "Send a REGISTER request to an outbound registration target with a expiration of 0")
881 };
882
883 static int load_module(void)
884 {
885         ast_sorcery_apply_default(ast_sip_get_sorcery(), "registration", "config", "pjsip.conf,criteria=type=registration");
886
887         if (ast_sorcery_object_register(ast_sip_get_sorcery(), "registration", sip_outbound_registration_alloc, NULL, sip_outbound_registration_apply)) {
888                 return AST_MODULE_LOAD_DECLINE;
889         }
890
891         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "type", "", OPT_NOOP_T, 0, 0);
892         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "server_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, server_uri));
893         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "client_uri", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, client_uri));
894         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "contact_user", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, contact_user));
895         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, transport));
896         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, outbound_proxy));
897         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "expiration", "3600", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, expiration));
898         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "retry_interval", "60", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, retry_interval));
899         ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "max_retries", "10", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, max_retries));
900         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));
901         ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "registration", "outbound_auth", "", outbound_auth_handler, NULL, 0, 0);
902         ast_sorcery_reload_object(ast_sip_get_sorcery(), "registration");
903         sip_outbound_registration_perform_all();
904
905         ast_cli_register_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration));
906         ast_manager_register_xml("PJSIPUnregister", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_unregister);
907         return AST_MODULE_LOAD_SUCCESS;
908 }
909
910 static int reload_module(void)
911 {
912         ast_sorcery_reload_object(ast_sip_get_sorcery(), "registration");
913         sip_outbound_registration_perform_all();
914         return 0;
915 }
916
917 static int unload_module(void)
918 {
919         ast_cli_unregister_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration));
920         ast_manager_unregister("PJSIPUnregister");
921         return 0;
922 }
923
924 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Outbound Registration Support",
925                 .load = load_module,
926                 .reload = reload_module,
927                 .unload = unload_module,
928                 .load_pri = AST_MODPRI_APP_DEPEND,
929                );