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