app_dial: Allow macro/gosub pre-bridge execution to occur on priorities
[asterisk/asterisk.git] / main / core_local.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013 Digium, Inc.
5  *
6  * Richard Mudgett <rmudgett@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 /*!
20  * \file
21  * \brief Local proxy channel driver.
22  *
23  * \author Richard Mudgett <rmudgett@digium.com>
24  *
25  * See Also:
26  * \arg \ref AstCREDITS
27  */
28
29 /*** MODULEINFO
30         <support_level>core</support_level>
31  ***/
32
33
34 #include "asterisk.h"
35
36 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
37
38 /* ------------------------------------------------------------------- */
39
40 #include "asterisk/channel.h"
41 #include "asterisk/pbx.h"
42 #include "asterisk/cli.h"
43 #include "asterisk/manager.h"
44 #include "asterisk/devicestate.h"
45 #include "asterisk/astobj2.h"
46 #include "asterisk/bridge.h"
47 #include "asterisk/core_unreal.h"
48 #include "asterisk/core_local.h"
49 #include "asterisk/stasis.h"
50 #include "asterisk/stasis_channels.h"
51 #include "asterisk/_private.h"
52 #include "asterisk/stasis_channels.h"
53
54 /*** DOCUMENTATION
55         <manager name="LocalOptimizeAway" language="en_US">
56                 <synopsis>
57                         Optimize away a local channel when possible.
58                 </synopsis>
59                 <syntax>
60                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
61                         <parameter name="Channel" required="true">
62                                 <para>The channel name to optimize away.</para>
63                         </parameter>
64                 </syntax>
65                 <description>
66                         <para>A local channel created with "/n" will not automatically optimize away.
67                         Calling this command on the local channel will clear that flag and allow
68                         it to optimize away if it's bridged or when it becomes bridged.</para>
69                 </description>
70         </manager>
71         <managerEvent language="en_US" name="LocalBridge">
72                 <managerEventInstance class="EVENT_FLAG_CALL">
73                         <synopsis>Raised when two halves of a Local Channel form a bridge.</synopsis>
74                         <syntax>
75                                 <channel_snapshot prefix="LocalOne"/>
76                                 <channel_snapshot prefix="LocalTwo"/>
77                                 <parameter name="Context">
78                                         <para>The context in the dialplan that Channel2 starts in.</para>
79                                 </parameter>
80                                 <parameter name="Exten">
81                                         <para>The extension in the dialplan that Channel2 starts in.</para>
82                                 </parameter>
83                                 <parameter name="LocalOptimization">
84                                         <enumlist>
85                                                 <enum name="Yes"/>
86                                                 <enum name="No"/>
87                                         </enumlist>
88                                 </parameter>
89                         </syntax>
90                 </managerEventInstance>
91         </managerEvent>
92         <managerEvent language="en_US" name="LocalOptimizationBegin">
93                 <managerEventInstance class="EVENT_FLAG_CALL">
94                         <synopsis>Raised when two halves of a Local Channel begin to optimize
95                         themselves out of the media path.</synopsis>
96                         <syntax>
97                                 <channel_snapshot prefix="LocalOne"/>
98                                 <channel_snapshot prefix="LocalTwo"/>
99                                 <channel_snapshot prefix="Source"/>
100                                 <parameter name="DestUniqueId">
101                                         <para>The unique ID of the bridge into which the local channel is optimizing.</para>
102                                 </parameter>
103                                 <parameter name="Id">
104                                         <para>Identification for the optimization operation.</para>
105                                 </parameter>
106                         </syntax>
107                         <see-also>
108                                 <ref type="managerEvent">LocalOptimizationEnd</ref>
109                                 <ref type="manager">LocalOptimizeAway</ref>
110                         </see-also>
111                 </managerEventInstance>
112         </managerEvent>
113         <managerEvent language="en_US" name="LocalOptimizationEnd">
114                 <managerEventInstance class="EVENT_FLAG_CALL">
115                         <synopsis>Raised when two halves of a Local Channel have finished optimizing
116                         themselves out of the media path.</synopsis>
117                         <syntax>
118                                 <channel_snapshot prefix="LocalOne"/>
119                                 <channel_snapshot prefix="LocalTwo"/>
120                                 <parameter name="Success">
121                                         <para>Indicates whether the local optimization succeeded.</para>
122                                 </parameter>
123                                 <parameter name="Id">
124                                         <para>Identification for the optimization operation. Matches the <replaceable>Id</replaceable>
125                                         from a previous <literal>LocalOptimizationBegin</literal></para>
126                                 </parameter>
127                         </syntax>
128                         <see-also>
129                                 <ref type="managerEvent">LocalOptimizationBegin</ref>
130                                 <ref type="manager">LocalOptimizeAway</ref>
131                         </see-also>
132                 </managerEventInstance>
133         </managerEvent>
134  ***/
135
136 static const char tdesc[] = "Local Proxy Channel Driver";
137
138 static struct ao2_container *locals;
139
140 static struct ast_channel *local_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause);
141 static int local_call(struct ast_channel *ast, const char *dest, int timeout);
142 static int local_hangup(struct ast_channel *ast);
143 static int local_devicestate(const char *data);
144 static void local_optimization_started_cb(struct ast_unreal_pvt *base, struct ast_channel *source,
145                 enum ast_unreal_channel_indicator dest, unsigned int id);
146 static void local_optimization_finished_cb(struct ast_unreal_pvt *base, int success, unsigned int id);
147
148 static struct ast_manager_event_blob *local_message_to_ami(struct stasis_message *msg);
149
150 /*!
151  * @{ \brief Define local channel message types.
152  */
153 STASIS_MESSAGE_TYPE_DEFN(ast_local_bridge_type,
154         .to_ami = local_message_to_ami,
155         );
156 STASIS_MESSAGE_TYPE_DEFN(ast_local_optimization_begin_type,
157         .to_ami = local_message_to_ami,
158         );
159 STASIS_MESSAGE_TYPE_DEFN(ast_local_optimization_end_type,
160         .to_ami = local_message_to_ami,
161         );
162 /*! @} */
163
164 /*! \brief Callbacks from the unreal core when channel optimization occurs */
165 struct ast_unreal_pvt_callbacks local_unreal_callbacks = {
166         .optimization_started = local_optimization_started_cb,
167         .optimization_finished = local_optimization_finished_cb,
168 };
169
170 /* PBX interface structure for channel registration */
171 static struct ast_channel_tech local_tech = {
172         .type = "Local",
173         .description = tdesc,
174         .requester = local_request,
175         .send_digit_begin = ast_unreal_digit_begin,
176         .send_digit_end = ast_unreal_digit_end,
177         .call = local_call,
178         .hangup = local_hangup,
179         .answer = ast_unreal_answer,
180         .read = ast_unreal_read,
181         .write = ast_unreal_write,
182         .write_video = ast_unreal_write,
183         .exception = ast_unreal_read,
184         .indicate = ast_unreal_indicate,
185         .fixup = ast_unreal_fixup,
186         .send_html = ast_unreal_sendhtml,
187         .send_text = ast_unreal_sendtext,
188         .devicestate = local_devicestate,
189         .queryoption = ast_unreal_queryoption,
190         .setoption = ast_unreal_setoption,
191 };
192
193 /*! What to do with the ;2 channel when ast_call() happens. */
194 enum local_call_action {
195         /* The ast_call() will run dialplan on the ;2 channel. */
196         LOCAL_CALL_ACTION_DIALPLAN,
197         /* The ast_call() will impart the ;2 channel into a bridge. */
198         LOCAL_CALL_ACTION_BRIDGE,
199         /* The ast_call() will masquerade the ;2 channel into a channel. */
200         LOCAL_CALL_ACTION_MASQUERADE,
201 };
202
203 /*! Join a bridge on ast_call() parameters. */
204 struct local_bridge {
205         /*! Bridge to join. */
206         struct ast_bridge *join;
207         /*! Channel to swap with when joining bridge. */
208         struct ast_channel *swap;
209         /*! Features that are specific to this channel when pushed into the bridge. */
210         struct ast_bridge_features *features;
211 };
212
213 /*!
214  * \brief the local pvt structure for all channels
215  *
216  * The local channel pvt has two ast_chan objects - the "owner" and the "next channel", the outbound channel
217  *
218  * ast_chan owner -> local_pvt -> ast_chan chan
219  */
220 struct local_pvt {
221         /*! Unreal channel driver base class values. */
222         struct ast_unreal_pvt base;
223         /*! Additional action arguments */
224         union {
225                 /*! Make ;2 join a bridge on ast_call(). */
226                 struct local_bridge bridge;
227                 /*! Make ;2 masquerade into this channel on ast_call(). */
228                 struct ast_channel *masq;
229         } action;
230         /*! What to do with the ;2 channel on ast_call(). */
231         enum local_call_action type;
232         /*! Context to call */
233         char context[AST_MAX_CONTEXT];
234         /*! Extension to call */
235         char exten[AST_MAX_EXTENSION];
236 };
237
238 struct ast_channel *ast_local_get_peer(struct ast_channel *ast)
239 {
240         struct local_pvt *p = ast_channel_tech_pvt(ast);
241         struct local_pvt *found;
242         struct ast_channel *peer;
243
244         if (!p) {
245                 return NULL;
246         }
247
248         found = p ? ao2_find(locals, p, 0) : NULL;
249         if (!found) {
250                 /* ast is either not a local channel or it has alredy been hungup */
251                 return NULL;
252         }
253         ao2_lock(found);
254         if (ast == p->base.owner) {
255                 peer = p->base.chan;
256         } else if (ast == p->base.chan) {
257                 peer = p->base.owner;
258         } else {
259                 peer = NULL;
260         }
261         if (peer) {
262                 ast_channel_ref(peer);
263         }
264         ao2_unlock(found);
265         ao2_ref(found, -1);
266         return peer;
267 }
268
269 /*! \brief Adds devicestate to local channels */
270 static int local_devicestate(const char *data)
271 {
272         int is_inuse = 0;
273         int res = AST_DEVICE_INVALID;
274         char *exten = ast_strdupa(data);
275         char *context;
276         char *opts;
277         struct local_pvt *lp;
278         struct ao2_iterator it;
279
280         /* Strip options if they exist */
281         opts = strchr(exten, '/');
282         if (opts) {
283                 *opts = '\0';
284         }
285
286         context = strchr(exten, '@');
287         if (!context) {
288                 ast_log(LOG_WARNING,
289                         "Someone used Local/%s somewhere without a @context. This is bad.\n", data);
290                 return AST_DEVICE_INVALID;
291         }
292         *context++ = '\0';
293
294         it = ao2_iterator_init(locals, 0);
295         for (; (lp = ao2_iterator_next(&it)); ao2_ref(lp, -1)) {
296                 ao2_lock(lp);
297                 if (!strcmp(exten, lp->exten)
298                         && !strcmp(context, lp->context)) {
299                         res = AST_DEVICE_NOT_INUSE;
300                         if (lp->base.owner
301                                 && ast_test_flag(&lp->base, AST_UNREAL_CARETAKER_THREAD)) {
302                                 is_inuse = 1;
303                         }
304                 }
305                 ao2_unlock(lp);
306                 if (is_inuse) {
307                         res = AST_DEVICE_INUSE;
308                         ao2_ref(lp, -1);
309                         break;
310                 }
311         }
312         ao2_iterator_destroy(&it);
313
314         if (res == AST_DEVICE_INVALID) {
315                 ast_debug(3, "Checking if extension %s@%s exists (devicestate)\n", exten, context);
316                 if (ast_exists_extension(NULL, context, exten, 1, NULL)) {
317                         res = AST_DEVICE_NOT_INUSE;
318                 }
319         }
320
321         return res;
322 }
323
324 static struct ast_multi_channel_blob *local_channel_optimization_blob(struct local_pvt *p,
325                 struct ast_json *json_object)
326 {
327         struct ast_multi_channel_blob *payload;
328         RAII_VAR(struct ast_channel_snapshot *, local_one_snapshot, NULL, ao2_cleanup);
329         RAII_VAR(struct ast_channel_snapshot *, local_two_snapshot, NULL, ao2_cleanup);
330
331         local_one_snapshot = ast_channel_snapshot_create(p->base.owner);
332         if (!local_one_snapshot) {
333                 return NULL;
334         }
335
336         local_two_snapshot = ast_channel_snapshot_create(p->base.chan);
337         if (!local_two_snapshot) {
338                 return NULL;
339         }
340
341         payload = ast_multi_channel_blob_create(json_object);
342         if (!payload) {
343                 return NULL;
344         }
345         ast_multi_channel_blob_add_channel(payload, "1", local_one_snapshot);
346         ast_multi_channel_blob_add_channel(payload, "2", local_two_snapshot);
347
348         return payload;
349 }
350
351 /*! \brief Callback for \ref ast_unreal_pvt_callbacks \ref optimization_started_cb */
352 static void local_optimization_started_cb(struct ast_unreal_pvt *base, struct ast_channel *source,
353                 enum ast_unreal_channel_indicator dest, unsigned int id)
354 {
355         RAII_VAR(struct ast_json *, json_object, ast_json_null(), ast_json_unref);
356         RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
357         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
358         struct local_pvt *p = (struct local_pvt *)base;
359
360         json_object = ast_json_pack("{s: i, s: i}",
361                         "dest", dest, "id", id);
362
363         if (!json_object) {
364                 return;
365         }
366
367         payload = local_channel_optimization_blob(p, json_object);
368         if (!payload) {
369                 return;
370         }
371
372         if (source) {
373                 RAII_VAR(struct ast_channel_snapshot *, source_snapshot, NULL, ao2_cleanup);
374                 source_snapshot = ast_channel_snapshot_create(source);
375                 if (!source_snapshot) {
376                         return;
377                 }
378
379                 ast_multi_channel_blob_add_channel(payload, "source", source_snapshot);
380         }
381
382         msg = stasis_message_create(ast_local_optimization_begin_type(), payload);
383         if (!msg) {
384                 return;
385         }
386
387         stasis_publish(ast_channel_topic(p->base.owner), msg);
388 }
389
390 /*! \brief Callback for \ref ast_unreal_pvt_callbacks \ref optimization_finished_cb */
391 static void local_optimization_finished_cb(struct ast_unreal_pvt *base, int success, unsigned int id)
392 {
393         RAII_VAR(struct ast_json *, json_object, ast_json_null(), ast_json_unref);
394         RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
395         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
396         struct local_pvt *p = (struct local_pvt *)base;
397
398         json_object = ast_json_pack("{s: i, s: i}", "success", success, "id", id);
399
400         if (!json_object) {
401                 return;
402         }
403
404         payload = local_channel_optimization_blob(p, json_object);
405         if (!payload) {
406                 return;
407         }
408
409         msg = stasis_message_create(ast_local_optimization_end_type(), payload);
410         if (!msg) {
411                 return;
412         }
413
414         stasis_publish(ast_channel_topic(p->base.owner), msg);
415 }
416
417 static struct ast_manager_event_blob *local_message_to_ami(struct stasis_message *message)
418 {
419         struct ast_multi_channel_blob *obj = stasis_message_data(message);
420         struct ast_json *blob = ast_multi_channel_blob_get_json(obj);
421         struct ast_channel_snapshot *local_snapshot_one;
422         struct ast_channel_snapshot *local_snapshot_two;
423         RAII_VAR(struct ast_str *, local_channel_one, NULL, ast_free);
424         RAII_VAR(struct ast_str *, local_channel_two, NULL, ast_free);
425         RAII_VAR(struct ast_str *, event_buffer, NULL, ast_free);
426         const char *event;
427
428         local_snapshot_one = ast_multi_channel_blob_get_channel(obj, "1");
429         local_snapshot_two = ast_multi_channel_blob_get_channel(obj, "2");
430         if (!local_snapshot_one || !local_snapshot_two) {
431                 return NULL;
432         }
433
434         event_buffer = ast_str_create(1024);
435         local_channel_one = ast_manager_build_channel_state_string_prefix(local_snapshot_one, "LocalOne");
436         local_channel_two = ast_manager_build_channel_state_string_prefix(local_snapshot_two, "LocalTwo");
437         if (!event_buffer || !local_channel_one || !local_channel_two) {
438                 return NULL;
439         }
440
441         if (stasis_message_type(message) == ast_local_optimization_begin_type()) {
442                 struct ast_channel_snapshot *source_snapshot;
443                 RAII_VAR(struct ast_str *, source_str, NULL, ast_free);
444                 const char *dest_uniqueid;
445
446                 source_snapshot = ast_multi_channel_blob_get_channel(obj, "source");
447                 if (source_snapshot) {
448                         source_str = ast_manager_build_channel_state_string_prefix(source_snapshot, "Source");
449                         if (!source_str) {
450                                 return NULL;
451                         }
452                 }
453
454                 dest_uniqueid = ast_json_object_get(blob, "dest") == AST_UNREAL_OWNER ?
455                                 local_snapshot_one->uniqueid : local_snapshot_two->uniqueid;
456
457                 event = "LocalOptimizationBegin";
458                 if (source_str) {
459                         ast_str_append(&event_buffer, 0, "%s", ast_str_buffer(source_str));
460                 }
461                 ast_str_append(&event_buffer, 0, "DestUniqueId: %s\r\n", dest_uniqueid);
462                 ast_str_append(&event_buffer, 0, "Id: %u\r\n", (unsigned int) ast_json_integer_get(ast_json_object_get(blob, "id")));
463         } else if (stasis_message_type(message) == ast_local_optimization_end_type()) {
464                 event = "LocalOptimizationEnd";
465                 ast_str_append(&event_buffer, 0, "Success: %s\r\n", ast_json_integer_get(ast_json_object_get(blob, "success")) ? "Yes" : "No");
466                 ast_str_append(&event_buffer, 0, "Id: %u\r\n", (unsigned int) ast_json_integer_get(ast_json_object_get(blob, "id")));
467         } else if (stasis_message_type(message) == ast_local_bridge_type()) {
468                 event = "LocalBridge";
469                 ast_str_append(&event_buffer, 0, "Context: %s\r\n", ast_json_string_get(ast_json_object_get(blob, "context")));
470                 ast_str_append(&event_buffer, 0, "Exten: %s\r\n", ast_json_string_get(ast_json_object_get(blob, "exten")));
471                 ast_str_append(&event_buffer, 0, "LocalOptimization: %s\r\n", ast_json_is_true(ast_json_object_get(blob, "can_optimize")) ? "Yes" : "No");
472         } else {
473                 return NULL;
474         }
475
476         return ast_manager_event_blob_create(EVENT_FLAG_CALL, event,
477                 "%s"
478                 "%s"
479                 "%s",
480                 ast_str_buffer(local_channel_one),
481                 ast_str_buffer(local_channel_two),
482                 ast_str_buffer(event_buffer));
483 }
484
485 /*!
486  * \internal
487  * \brief Post the \ref ast_local_bridge_type \ref stasis message
488  * \since 12.0.0
489  *
490  * \param p local_pvt to raise the local bridge message
491  *
492  * \return Nothing
493  */
494 static void publish_local_bridge_message(struct local_pvt *p)
495 {
496         RAII_VAR(struct ast_multi_channel_blob *, multi_blob, NULL, ao2_cleanup);
497         RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
498         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
499         RAII_VAR(struct ast_channel_snapshot *, one_snapshot, NULL, ao2_cleanup);
500         RAII_VAR(struct ast_channel_snapshot *, two_snapshot, NULL, ao2_cleanup);
501         struct ast_channel *owner;
502         struct ast_channel *chan;
503
504         ast_unreal_lock_all(&p->base, &chan, &owner);
505
506         blob = ast_json_pack("{s: s, s: s, s: b}",
507                 "context", p->context,
508                 "exten", p->exten,
509                 "can_optimize", !ast_test_flag(&p->base, AST_UNREAL_NO_OPTIMIZATION));
510         if (!blob) {
511                 goto end;
512         }
513
514         multi_blob = ast_multi_channel_blob_create(blob);
515         if (!multi_blob) {
516                 goto end;
517         }
518
519         one_snapshot = ast_channel_snapshot_create(owner);
520         if (!one_snapshot) {
521                 goto end;
522         }
523
524         two_snapshot = ast_channel_snapshot_create(chan);
525         if (!two_snapshot) {
526                 goto end;
527         }
528
529         ast_multi_channel_blob_add_channel(multi_blob, "1", one_snapshot);
530         ast_multi_channel_blob_add_channel(multi_blob, "2", two_snapshot);
531
532         msg = stasis_message_create(ast_local_bridge_type(), multi_blob);
533         if (!msg) {
534                 goto end;
535         }
536
537         stasis_publish(ast_channel_topic(owner), msg);
538
539 end:
540         ast_channel_unlock(owner);
541         ast_channel_unref(owner);
542
543         ast_channel_unlock(chan);
544         ast_channel_unref(chan);
545
546         ao2_unlock(&p->base);
547 }
548
549 int ast_local_setup_bridge(struct ast_channel *ast, struct ast_bridge *bridge, struct ast_channel *swap, struct ast_bridge_features *features)
550 {
551         struct local_pvt *p;
552         struct local_pvt *found;
553         int res = -1;
554
555         /* Sanity checks. */
556         if (!ast || !bridge) {
557                 ast_bridge_features_destroy(features);
558                 return -1;
559         }
560
561         ast_channel_lock(ast);
562         p = ast_channel_tech_pvt(ast);
563         ast_channel_unlock(ast);
564
565         found = p ? ao2_find(locals, p, 0) : NULL;
566         if (found) {
567                 ao2_lock(found);
568                 if (found->type == LOCAL_CALL_ACTION_DIALPLAN
569                         && found->base.owner
570                         && found->base.chan
571                         && !ast_test_flag(&found->base, AST_UNREAL_CARETAKER_THREAD)) {
572                         ao2_ref(bridge, +1);
573                         if (swap) {
574                                 ast_channel_ref(swap);
575                         }
576                         found->type = LOCAL_CALL_ACTION_BRIDGE;
577                         found->action.bridge.join = bridge;
578                         found->action.bridge.swap = swap;
579                         found->action.bridge.features = features;
580                         res = 0;
581                 } else {
582                         ast_bridge_features_destroy(features);
583                 }
584                 ao2_unlock(found);
585                 ao2_ref(found, -1);
586         }
587
588         return res;
589 }
590
591 int ast_local_setup_masquerade(struct ast_channel *ast, struct ast_channel *masq)
592 {
593         struct local_pvt *p;
594         struct local_pvt *found;
595         int res = -1;
596
597         /* Sanity checks. */
598         if (!ast || !masq) {
599                 return -1;
600         }
601
602         ast_channel_lock(ast);
603         p = ast_channel_tech_pvt(ast);
604         ast_channel_unlock(ast);
605
606         found = p ? ao2_find(locals, p, 0) : NULL;
607         if (found) {
608                 ao2_lock(found);
609                 if (found->type == LOCAL_CALL_ACTION_DIALPLAN
610                         && found->base.owner
611                         && found->base.chan
612                         && !ast_test_flag(&found->base, AST_UNREAL_CARETAKER_THREAD)) {
613                         ast_channel_ref(masq);
614                         found->type = LOCAL_CALL_ACTION_MASQUERADE;
615                         found->action.masq = masq;
616                         res = 0;
617                 }
618                 ao2_unlock(found);
619                 ao2_ref(found, -1);
620         }
621
622         return res;
623 }
624
625 /*! \brief Initiate new call, part of PBX interface
626  *         dest is the dial string */
627 static int local_call(struct ast_channel *ast, const char *dest, int timeout)
628 {
629         struct local_pvt *p = ast_channel_tech_pvt(ast);
630         int pvt_locked = 0;
631
632         struct ast_channel *owner = NULL;
633         struct ast_channel *chan = NULL;
634         int res;
635         char *reduced_dest = ast_strdupa(dest);
636         char *slash;
637         const char *chan_cid;
638
639         if (!p) {
640                 return -1;
641         }
642
643         /* since we are letting go of channel locks that were locked coming into
644          * this function, then we need to give the tech pvt a ref */
645         ao2_ref(p, 1);
646         ast_channel_unlock(ast);
647
648         ast_unreal_lock_all(&p->base, &chan, &owner);
649         pvt_locked = 1;
650
651         if (owner != ast) {
652                 res = -1;
653                 goto return_cleanup;
654         }
655
656         if (!owner || !chan) {
657                 res = -1;
658                 goto return_cleanup;
659         }
660
661         ast_unreal_call_setup(owner, chan);
662
663         /*
664          * If the local channel has /n on the end of it, we need to lop
665          * that off for our argument to setting up the CC_INTERFACES
666          * variable.
667          */
668         if ((slash = strrchr(reduced_dest, '/'))) {
669                 *slash = '\0';
670         }
671         ast_set_cc_interfaces_chanvar(chan, reduced_dest);
672
673         ao2_unlock(p);
674         pvt_locked = 0;
675
676         ast_channel_unlock(owner);
677
678         chan_cid = S_COR(ast_channel_caller(chan)->id.number.valid,
679                 ast_channel_caller(chan)->id.number.str, NULL);
680         if (chan_cid) {
681                 chan_cid = ast_strdupa(chan_cid);
682         }
683         ast_channel_unlock(chan);
684
685         res = -1;
686         switch (p->type) {
687         case LOCAL_CALL_ACTION_DIALPLAN:
688                 if (!ast_exists_extension(NULL, p->context, p->exten, 1, chan_cid)) {
689                         ast_log(LOG_NOTICE, "No such extension/context %s@%s while calling Local channel\n",
690                                 p->exten, p->context);
691                 } else {
692                         publish_local_bridge_message(p);
693
694                         /* Start switch on sub channel */
695                         res = ast_pbx_start(chan);
696                 }
697                 break;
698         case LOCAL_CALL_ACTION_BRIDGE:
699                 publish_local_bridge_message(p);
700                 ast_answer(chan);
701                 res = ast_bridge_impart(p->action.bridge.join, chan, p->action.bridge.swap,
702                         p->action.bridge.features, AST_BRIDGE_IMPART_CHAN_INDEPENDENT);
703                 ao2_ref(p->action.bridge.join, -1);
704                 p->action.bridge.join = NULL;
705                 ao2_cleanup(p->action.bridge.swap);
706                 p->action.bridge.swap = NULL;
707                 p->action.bridge.features = NULL;
708                 break;
709         case LOCAL_CALL_ACTION_MASQUERADE:
710                 publish_local_bridge_message(p);
711                 ast_answer(chan);
712                 res = ast_channel_move(p->action.masq, chan);
713                 if (!res) {
714                         /* Chan is now an orphaned zombie.  Destroy it. */
715                         ast_hangup(chan);
716                 }
717                 p->action.masq = ast_channel_unref(p->action.masq);
718                 break;
719         }
720         if (!res) {
721                 ao2_lock(p);
722                 ast_set_flag(&p->base, AST_UNREAL_CARETAKER_THREAD);
723                 ao2_unlock(p);
724         }
725
726         /* we already unlocked them, clear them here so the cleanup label won't touch them. */
727         owner = ast_channel_unref(owner);
728         chan = ast_channel_unref(chan);
729
730 return_cleanup:
731         if (p) {
732                 if (pvt_locked) {
733                         ao2_unlock(p);
734                 }
735                 ao2_ref(p, -1);
736         }
737         if (chan) {
738                 ast_channel_unlock(chan);
739                 ast_channel_unref(chan);
740         }
741
742         /*
743          * owner is supposed to be == to ast, if it is, don't unlock it
744          * because ast must exit locked
745          */
746         if (owner) {
747                 if (owner != ast) {
748                         ast_channel_unlock(owner);
749                         ast_channel_lock(ast);
750                 }
751                 ast_channel_unref(owner);
752         } else {
753                 /* we have to exit with ast locked */
754                 ast_channel_lock(ast);
755         }
756
757         return res;
758 }
759
760 /*! \brief Hangup a call through the local proxy channel */
761 static int local_hangup(struct ast_channel *ast)
762 {
763         struct local_pvt *p = ast_channel_tech_pvt(ast);
764         int res;
765
766         if (!p) {
767                 return -1;
768         }
769
770         /* give the pvt a ref to fulfill calling requirements. */
771         ao2_ref(p, +1);
772         res = ast_unreal_hangup(&p->base, ast);
773         if (!res) {
774                 int unlink;
775
776                 ao2_lock(p);
777                 unlink = !p->base.owner && !p->base.chan;
778                 ao2_unlock(p);
779                 if (unlink) {
780                         ao2_unlink(locals, p);
781                 }
782         }
783         ao2_ref(p, -1);
784
785         return res;
786 }
787
788 /*!
789  * \internal
790  * \brief struct local_pvt destructor.
791  *
792  * \param vdoomed Object to destroy.
793  *
794  * \return Nothing
795  */
796 static void local_pvt_destructor(void *vdoomed)
797 {
798         struct local_pvt *doomed = vdoomed;
799
800         switch (doomed->type) {
801         case LOCAL_CALL_ACTION_DIALPLAN:
802                 break;
803         case LOCAL_CALL_ACTION_BRIDGE:
804                 ao2_cleanup(doomed->action.bridge.join);
805                 ao2_cleanup(doomed->action.bridge.swap);
806                 ast_bridge_features_destroy(doomed->action.bridge.features);
807                 break;
808         case LOCAL_CALL_ACTION_MASQUERADE:
809                 ao2_cleanup(doomed->action.masq);
810                 break;
811         }
812         ast_unreal_destructor(&doomed->base);
813 }
814
815 /*! \brief Create a call structure */
816 static struct local_pvt *local_alloc(const char *data, struct ast_format_cap *cap)
817 {
818         struct local_pvt *pvt;
819         char *parse;
820         char *context;
821         char *opts;
822
823         pvt = (struct local_pvt *) ast_unreal_alloc(sizeof(*pvt), local_pvt_destructor, cap);
824         if (!pvt) {
825                 return NULL;
826         }
827         pvt->base.callbacks = &local_unreal_callbacks;
828
829         parse = ast_strdupa(data);
830
831         /*
832          * Local channels intercept MOH by default.
833          *
834          * This is a silly default because it represents state held by
835          * the local channels.  Unless local channel optimization is
836          * disabled, the state will dissapear when the local channels
837          * optimize out.
838          */
839         ast_set_flag(&pvt->base, AST_UNREAL_MOH_INTERCEPT);
840
841         /* Look for options */
842         if ((opts = strchr(parse, '/'))) {
843                 *opts++ = '\0';
844                 if (strchr(opts, 'n')) {
845                         ast_set_flag(&pvt->base, AST_UNREAL_NO_OPTIMIZATION);
846                 }
847                 if (strchr(opts, 'j')) {
848                         if (ast_test_flag(&pvt->base, AST_UNREAL_NO_OPTIMIZATION)) {
849                                 ast_set_flag(&pvt->base.jb_conf, AST_JB_ENABLED);
850                         } else {
851                                 ast_log(LOG_ERROR, "You must use the 'n' option with the 'j' option to enable the jitter buffer\n");
852                         }
853                 }
854                 if (strchr(opts, 'm')) {
855                         ast_clear_flag(&pvt->base, AST_UNREAL_MOH_INTERCEPT);
856                 }
857         }
858
859         /* Look for a context */
860         if ((context = strchr(parse, '@'))) {
861                 *context++ = '\0';
862         }
863
864         ast_copy_string(pvt->context, S_OR(context, "default"), sizeof(pvt->context));
865         ast_copy_string(pvt->exten, parse, sizeof(pvt->exten));
866         snprintf(pvt->base.name, sizeof(pvt->base.name), "%s@%s", pvt->exten, pvt->context);
867
868         return pvt; /* this is returned with a ref */
869 }
870
871 /*! \brief Part of PBX interface */
872 static struct ast_channel *local_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
873 {
874         struct local_pvt *p;
875         struct ast_channel *chan;
876         struct ast_callid *callid;
877
878         /* Allocate a new private structure and then Asterisk channels */
879         p = local_alloc(data, cap);
880         if (!p) {
881                 return NULL;
882         }
883         callid = ast_read_threadstorage_callid();
884         chan = ast_unreal_new_channels(&p->base, &local_tech, AST_STATE_DOWN, AST_STATE_RING,
885                 p->exten, p->context, requestor, callid);
886         if (chan) {
887                 ao2_link(locals, p);
888         }
889         if (callid) {
890                 ast_callid_unref(callid);
891         }
892         ao2_ref(p, -1); /* kill the ref from the alloc */
893
894         return chan;
895 }
896
897 /*! \brief CLI command "local show channels" */
898 static char *locals_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
899 {
900         struct local_pvt *p;
901         struct ao2_iterator it;
902
903         switch (cmd) {
904         case CLI_INIT:
905                 e->command = "local show channels";
906                 e->usage =
907                         "Usage: local show channels\n"
908                         "       Provides summary information on active local proxy channels.\n";
909                 return NULL;
910         case CLI_GENERATE:
911                 return NULL;
912         }
913
914         if (a->argc != 3) {
915                 return CLI_SHOWUSAGE;
916         }
917
918         if (ao2_container_count(locals) == 0) {
919                 ast_cli(a->fd, "No local channels in use\n");
920                 return RESULT_SUCCESS;
921         }
922
923         it = ao2_iterator_init(locals, 0);
924         while ((p = ao2_iterator_next(&it))) {
925                 ao2_lock(p);
926                 ast_cli(a->fd, "%s -- %s\n",
927                         p->base.owner ? ast_channel_name(p->base.owner) : "<unowned>",
928                         p->base.name);
929                 ao2_unlock(p);
930                 ao2_ref(p, -1);
931         }
932         ao2_iterator_destroy(&it);
933
934         return CLI_SUCCESS;
935 }
936
937 static struct ast_cli_entry cli_local[] = {
938         AST_CLI_DEFINE(locals_show, "List status of local channels"),
939 };
940
941 static int manager_optimize_away(struct mansession *s, const struct message *m)
942 {
943         const char *channel;
944         struct local_pvt *p;
945         struct local_pvt *found;
946         struct ast_channel *chan;
947
948         channel = astman_get_header(m, "Channel");
949         if (ast_strlen_zero(channel)) {
950                 astman_send_error(s, m, "'Channel' not specified.");
951                 return 0;
952         }
953
954         chan = ast_channel_get_by_name(channel);
955         if (!chan) {
956                 astman_send_error(s, m, "Channel does not exist.");
957                 return 0;
958         }
959
960         p = ast_channel_tech_pvt(chan);
961         ast_channel_unref(chan);
962
963         found = p ? ao2_find(locals, p, 0) : NULL;
964         if (found) {
965                 ao2_lock(found);
966                 ast_clear_flag(&found->base, AST_UNREAL_NO_OPTIMIZATION);
967                 ao2_unlock(found);
968                 ao2_ref(found, -1);
969                 astman_send_ack(s, m, "Queued channel to be optimized away");
970         } else {
971                 astman_send_error(s, m, "Unable to find channel");
972         }
973
974         return 0;
975 }
976
977
978 static int locals_cmp_cb(void *obj, void *arg, int flags)
979 {
980         return (obj == arg) ? CMP_MATCH : 0;
981 }
982
983 /*!
984  * \internal
985  * \brief Shutdown the local proxy channel.
986  * \since 12.0.0
987  *
988  * \return Nothing
989  */
990 static void local_shutdown(void)
991 {
992         struct local_pvt *p;
993         struct ao2_iterator it;
994
995         /* First, take us out of the channel loop */
996         ast_cli_unregister_multiple(cli_local, ARRAY_LEN(cli_local));
997         ast_manager_unregister("LocalOptimizeAway");
998         ast_channel_unregister(&local_tech);
999
1000         it = ao2_iterator_init(locals, 0);
1001         while ((p = ao2_iterator_next(&it))) {
1002                 if (p->base.owner) {
1003                         ast_softhangup(p->base.owner, AST_SOFTHANGUP_APPUNLOAD);
1004                 }
1005                 ao2_ref(p, -1);
1006         }
1007         ao2_iterator_destroy(&it);
1008         ao2_ref(locals, -1);
1009         locals = NULL;
1010
1011         ast_format_cap_destroy(local_tech.capabilities);
1012
1013         STASIS_MESSAGE_TYPE_CLEANUP(ast_local_optimization_begin_type);
1014         STASIS_MESSAGE_TYPE_CLEANUP(ast_local_optimization_end_type);
1015         STASIS_MESSAGE_TYPE_CLEANUP(ast_local_bridge_type);
1016 }
1017
1018 int ast_local_init(void)
1019 {
1020
1021         if (STASIS_MESSAGE_TYPE_INIT(ast_local_optimization_begin_type)) {
1022                 return -1;
1023         }
1024
1025         if (STASIS_MESSAGE_TYPE_INIT(ast_local_optimization_end_type)) {
1026                 return -1;
1027         }
1028
1029         if (STASIS_MESSAGE_TYPE_INIT(ast_local_bridge_type)) {
1030                 return -1;
1031         }
1032
1033         if (!(local_tech.capabilities = ast_format_cap_alloc(0))) {
1034                 return -1;
1035         }
1036         ast_format_cap_add_all(local_tech.capabilities);
1037
1038         locals = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, locals_cmp_cb);
1039         if (!locals) {
1040                 ast_format_cap_destroy(local_tech.capabilities);
1041                 return -1;
1042         }
1043
1044         /* Make sure we can register our channel type */
1045         if (ast_channel_register(&local_tech)) {
1046                 ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n");
1047                 ao2_ref(locals, -1);
1048                 ast_format_cap_destroy(local_tech.capabilities);
1049                 return -1;
1050         }
1051         ast_cli_register_multiple(cli_local, ARRAY_LEN(cli_local));
1052         ast_manager_register_xml_core("LocalOptimizeAway", EVENT_FLAG_SYSTEM|EVENT_FLAG_CALL, manager_optimize_away);
1053
1054         ast_register_atexit(local_shutdown);
1055         return 0;
1056 }