Add channel locking for channel snapshot creation.
[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_unlock(chan);
542         ao2_unlock(p);
543 }
544
545 int ast_local_setup_bridge(struct ast_channel *ast, struct ast_bridge *bridge, struct ast_channel *swap, struct ast_bridge_features *features)
546 {
547         struct local_pvt *p;
548         struct local_pvt *found;
549         int res = -1;
550
551         /* Sanity checks. */
552         if (!ast || !bridge) {
553                 ast_bridge_features_destroy(features);
554                 return -1;
555         }
556
557         ast_channel_lock(ast);
558         p = ast_channel_tech_pvt(ast);
559         ast_channel_unlock(ast);
560
561         found = p ? ao2_find(locals, p, 0) : NULL;
562         if (found) {
563                 ao2_lock(found);
564                 if (found->type == LOCAL_CALL_ACTION_DIALPLAN
565                         && found->base.owner
566                         && found->base.chan
567                         && !ast_test_flag(&found->base, AST_UNREAL_CARETAKER_THREAD)) {
568                         ao2_ref(bridge, +1);
569                         if (swap) {
570                                 ast_channel_ref(swap);
571                         }
572                         found->type = LOCAL_CALL_ACTION_BRIDGE;
573                         found->action.bridge.join = bridge;
574                         found->action.bridge.swap = swap;
575                         found->action.bridge.features = features;
576                         res = 0;
577                 } else {
578                         ast_bridge_features_destroy(features);
579                 }
580                 ao2_unlock(found);
581                 ao2_ref(found, -1);
582         }
583
584         return res;
585 }
586
587 int ast_local_setup_masquerade(struct ast_channel *ast, struct ast_channel *masq)
588 {
589         struct local_pvt *p;
590         struct local_pvt *found;
591         int res = -1;
592
593         /* Sanity checks. */
594         if (!ast || !masq) {
595                 return -1;
596         }
597
598         ast_channel_lock(ast);
599         p = ast_channel_tech_pvt(ast);
600         ast_channel_unlock(ast);
601
602         found = p ? ao2_find(locals, p, 0) : NULL;
603         if (found) {
604                 ao2_lock(found);
605                 if (found->type == LOCAL_CALL_ACTION_DIALPLAN
606                         && found->base.owner
607                         && found->base.chan
608                         && !ast_test_flag(&found->base, AST_UNREAL_CARETAKER_THREAD)) {
609                         ast_channel_ref(masq);
610                         found->type = LOCAL_CALL_ACTION_MASQUERADE;
611                         found->action.masq = masq;
612                         res = 0;
613                 }
614                 ao2_unlock(found);
615                 ao2_ref(found, -1);
616         }
617
618         return res;
619 }
620
621 /*! \brief Initiate new call, part of PBX interface
622  *         dest is the dial string */
623 static int local_call(struct ast_channel *ast, const char *dest, int timeout)
624 {
625         struct local_pvt *p = ast_channel_tech_pvt(ast);
626         int pvt_locked = 0;
627
628         struct ast_channel *owner = NULL;
629         struct ast_channel *chan = NULL;
630         int res;
631         char *reduced_dest = ast_strdupa(dest);
632         char *slash;
633         const char *chan_cid;
634
635         if (!p) {
636                 return -1;
637         }
638
639         /* since we are letting go of channel locks that were locked coming into
640          * this function, then we need to give the tech pvt a ref */
641         ao2_ref(p, 1);
642         ast_channel_unlock(ast);
643
644         ast_unreal_lock_all(&p->base, &chan, &owner);
645         pvt_locked = 1;
646
647         if (owner != ast) {
648                 res = -1;
649                 goto return_cleanup;
650         }
651
652         if (!owner || !chan) {
653                 res = -1;
654                 goto return_cleanup;
655         }
656
657         ast_unreal_call_setup(owner, chan);
658
659         /*
660          * If the local channel has /n on the end of it, we need to lop
661          * that off for our argument to setting up the CC_INTERFACES
662          * variable.
663          */
664         if ((slash = strrchr(reduced_dest, '/'))) {
665                 *slash = '\0';
666         }
667         ast_set_cc_interfaces_chanvar(chan, reduced_dest);
668
669         ao2_unlock(p);
670         pvt_locked = 0;
671
672         ast_channel_unlock(owner);
673
674         chan_cid = S_COR(ast_channel_caller(chan)->id.number.valid,
675                 ast_channel_caller(chan)->id.number.str, NULL);
676         if (chan_cid) {
677                 chan_cid = ast_strdupa(chan_cid);
678         }
679         ast_channel_unlock(chan);
680
681         res = -1;
682         switch (p->type) {
683         case LOCAL_CALL_ACTION_DIALPLAN:
684                 if (!ast_exists_extension(NULL, p->context, p->exten, 1, chan_cid)) {
685                         ast_log(LOG_NOTICE, "No such extension/context %s@%s while calling Local channel\n",
686                                 p->exten, p->context);
687                 } else {
688                         publish_local_bridge_message(p);
689
690                         /* Start switch on sub channel */
691                         res = ast_pbx_start(chan);
692                 }
693                 break;
694         case LOCAL_CALL_ACTION_BRIDGE:
695                 publish_local_bridge_message(p);
696                 ast_answer(chan);
697                 res = ast_bridge_impart(p->action.bridge.join, chan, p->action.bridge.swap,
698                         p->action.bridge.features, AST_BRIDGE_IMPART_CHAN_INDEPENDENT);
699                 ao2_ref(p->action.bridge.join, -1);
700                 p->action.bridge.join = NULL;
701                 ao2_cleanup(p->action.bridge.swap);
702                 p->action.bridge.swap = NULL;
703                 p->action.bridge.features = NULL;
704                 break;
705         case LOCAL_CALL_ACTION_MASQUERADE:
706                 publish_local_bridge_message(p);
707                 ast_answer(chan);
708                 res = ast_channel_move(p->action.masq, chan);
709                 if (!res) {
710                         /* Chan is now an orphaned zombie.  Destroy it. */
711                         ast_hangup(chan);
712                 }
713                 p->action.masq = ast_channel_unref(p->action.masq);
714                 break;
715         }
716         if (!res) {
717                 ao2_lock(p);
718                 ast_set_flag(&p->base, AST_UNREAL_CARETAKER_THREAD);
719                 ao2_unlock(p);
720         }
721
722         /* we already unlocked them, clear them here so the cleanup label won't touch them. */
723         owner = ast_channel_unref(owner);
724         chan = ast_channel_unref(chan);
725
726 return_cleanup:
727         if (p) {
728                 if (pvt_locked) {
729                         ao2_unlock(p);
730                 }
731                 ao2_ref(p, -1);
732         }
733         if (chan) {
734                 ast_channel_unlock(chan);
735                 ast_channel_unref(chan);
736         }
737
738         /*
739          * owner is supposed to be == to ast, if it is, don't unlock it
740          * because ast must exit locked
741          */
742         if (owner) {
743                 if (owner != ast) {
744                         ast_channel_unlock(owner);
745                         ast_channel_lock(ast);
746                 }
747                 ast_channel_unref(owner);
748         } else {
749                 /* we have to exit with ast locked */
750                 ast_channel_lock(ast);
751         }
752
753         return res;
754 }
755
756 /*! \brief Hangup a call through the local proxy channel */
757 static int local_hangup(struct ast_channel *ast)
758 {
759         struct local_pvt *p = ast_channel_tech_pvt(ast);
760         int res;
761
762         if (!p) {
763                 return -1;
764         }
765
766         /* give the pvt a ref to fulfill calling requirements. */
767         ao2_ref(p, +1);
768         res = ast_unreal_hangup(&p->base, ast);
769         if (!res) {
770                 int unlink;
771
772                 ao2_lock(p);
773                 unlink = !p->base.owner && !p->base.chan;
774                 ao2_unlock(p);
775                 if (unlink) {
776                         ao2_unlink(locals, p);
777                 }
778         }
779         ao2_ref(p, -1);
780
781         return res;
782 }
783
784 /*!
785  * \internal
786  * \brief struct local_pvt destructor.
787  *
788  * \param vdoomed Object to destroy.
789  *
790  * \return Nothing
791  */
792 static void local_pvt_destructor(void *vdoomed)
793 {
794         struct local_pvt *doomed = vdoomed;
795
796         switch (doomed->type) {
797         case LOCAL_CALL_ACTION_DIALPLAN:
798                 break;
799         case LOCAL_CALL_ACTION_BRIDGE:
800                 ao2_cleanup(doomed->action.bridge.join);
801                 ao2_cleanup(doomed->action.bridge.swap);
802                 ast_bridge_features_destroy(doomed->action.bridge.features);
803                 break;
804         case LOCAL_CALL_ACTION_MASQUERADE:
805                 ao2_cleanup(doomed->action.masq);
806                 break;
807         }
808         ast_unreal_destructor(&doomed->base);
809 }
810
811 /*! \brief Create a call structure */
812 static struct local_pvt *local_alloc(const char *data, struct ast_format_cap *cap)
813 {
814         struct local_pvt *pvt;
815         char *parse;
816         char *context;
817         char *opts;
818
819         pvt = (struct local_pvt *) ast_unreal_alloc(sizeof(*pvt), local_pvt_destructor, cap);
820         if (!pvt) {
821                 return NULL;
822         }
823         pvt->base.callbacks = &local_unreal_callbacks;
824
825         parse = ast_strdupa(data);
826
827         /*
828          * Local channels intercept MOH by default.
829          *
830          * This is a silly default because it represents state held by
831          * the local channels.  Unless local channel optimization is
832          * disabled, the state will dissapear when the local channels
833          * optimize out.
834          */
835         ast_set_flag(&pvt->base, AST_UNREAL_MOH_INTERCEPT);
836
837         /* Look for options */
838         if ((opts = strchr(parse, '/'))) {
839                 *opts++ = '\0';
840                 if (strchr(opts, 'n')) {
841                         ast_set_flag(&pvt->base, AST_UNREAL_NO_OPTIMIZATION);
842                 }
843                 if (strchr(opts, 'j')) {
844                         if (ast_test_flag(&pvt->base, AST_UNREAL_NO_OPTIMIZATION)) {
845                                 ast_set_flag(&pvt->base.jb_conf, AST_JB_ENABLED);
846                         } else {
847                                 ast_log(LOG_ERROR, "You must use the 'n' option with the 'j' option to enable the jitter buffer\n");
848                         }
849                 }
850                 if (strchr(opts, 'm')) {
851                         ast_clear_flag(&pvt->base, AST_UNREAL_MOH_INTERCEPT);
852                 }
853         }
854
855         /* Look for a context */
856         if ((context = strchr(parse, '@'))) {
857                 *context++ = '\0';
858         }
859
860         ast_copy_string(pvt->context, S_OR(context, "default"), sizeof(pvt->context));
861         ast_copy_string(pvt->exten, parse, sizeof(pvt->exten));
862         snprintf(pvt->base.name, sizeof(pvt->base.name), "%s@%s", pvt->exten, pvt->context);
863
864         return pvt; /* this is returned with a ref */
865 }
866
867 /*! \brief Part of PBX interface */
868 static struct ast_channel *local_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
869 {
870         struct local_pvt *p;
871         struct ast_channel *chan;
872         struct ast_callid *callid;
873
874         /* Allocate a new private structure and then Asterisk channels */
875         p = local_alloc(data, cap);
876         if (!p) {
877                 return NULL;
878         }
879         callid = ast_read_threadstorage_callid();
880         chan = ast_unreal_new_channels(&p->base, &local_tech, AST_STATE_DOWN, AST_STATE_RING,
881                 p->exten, p->context, requestor, callid);
882         if (chan) {
883                 ao2_link(locals, p);
884         }
885         if (callid) {
886                 ast_callid_unref(callid);
887         }
888         ao2_ref(p, -1); /* kill the ref from the alloc */
889
890         return chan;
891 }
892
893 /*! \brief CLI command "local show channels" */
894 static char *locals_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
895 {
896         struct local_pvt *p;
897         struct ao2_iterator it;
898
899         switch (cmd) {
900         case CLI_INIT:
901                 e->command = "local show channels";
902                 e->usage =
903                         "Usage: local show channels\n"
904                         "       Provides summary information on active local proxy channels.\n";
905                 return NULL;
906         case CLI_GENERATE:
907                 return NULL;
908         }
909
910         if (a->argc != 3) {
911                 return CLI_SHOWUSAGE;
912         }
913
914         if (ao2_container_count(locals) == 0) {
915                 ast_cli(a->fd, "No local channels in use\n");
916                 return RESULT_SUCCESS;
917         }
918
919         it = ao2_iterator_init(locals, 0);
920         while ((p = ao2_iterator_next(&it))) {
921                 ao2_lock(p);
922                 ast_cli(a->fd, "%s -- %s\n",
923                         p->base.owner ? ast_channel_name(p->base.owner) : "<unowned>",
924                         p->base.name);
925                 ao2_unlock(p);
926                 ao2_ref(p, -1);
927         }
928         ao2_iterator_destroy(&it);
929
930         return CLI_SUCCESS;
931 }
932
933 static struct ast_cli_entry cli_local[] = {
934         AST_CLI_DEFINE(locals_show, "List status of local channels"),
935 };
936
937 static int manager_optimize_away(struct mansession *s, const struct message *m)
938 {
939         const char *channel;
940         struct local_pvt *p;
941         struct local_pvt *found;
942         struct ast_channel *chan;
943
944         channel = astman_get_header(m, "Channel");
945         if (ast_strlen_zero(channel)) {
946                 astman_send_error(s, m, "'Channel' not specified.");
947                 return 0;
948         }
949
950         chan = ast_channel_get_by_name(channel);
951         if (!chan) {
952                 astman_send_error(s, m, "Channel does not exist.");
953                 return 0;
954         }
955
956         p = ast_channel_tech_pvt(chan);
957         ast_channel_unref(chan);
958
959         found = p ? ao2_find(locals, p, 0) : NULL;
960         if (found) {
961                 ao2_lock(found);
962                 ast_clear_flag(&found->base, AST_UNREAL_NO_OPTIMIZATION);
963                 ao2_unlock(found);
964                 ao2_ref(found, -1);
965                 astman_send_ack(s, m, "Queued channel to be optimized away");
966         } else {
967                 astman_send_error(s, m, "Unable to find channel");
968         }
969
970         return 0;
971 }
972
973
974 static int locals_cmp_cb(void *obj, void *arg, int flags)
975 {
976         return (obj == arg) ? CMP_MATCH : 0;
977 }
978
979 /*!
980  * \internal
981  * \brief Shutdown the local proxy channel.
982  * \since 12.0.0
983  *
984  * \return Nothing
985  */
986 static void local_shutdown(void)
987 {
988         struct local_pvt *p;
989         struct ao2_iterator it;
990
991         /* First, take us out of the channel loop */
992         ast_cli_unregister_multiple(cli_local, ARRAY_LEN(cli_local));
993         ast_manager_unregister("LocalOptimizeAway");
994         ast_channel_unregister(&local_tech);
995
996         it = ao2_iterator_init(locals, 0);
997         while ((p = ao2_iterator_next(&it))) {
998                 if (p->base.owner) {
999                         ast_softhangup(p->base.owner, AST_SOFTHANGUP_APPUNLOAD);
1000                 }
1001                 ao2_ref(p, -1);
1002         }
1003         ao2_iterator_destroy(&it);
1004         ao2_ref(locals, -1);
1005         locals = NULL;
1006
1007         ast_format_cap_destroy(local_tech.capabilities);
1008
1009         STASIS_MESSAGE_TYPE_CLEANUP(ast_local_optimization_begin_type);
1010         STASIS_MESSAGE_TYPE_CLEANUP(ast_local_optimization_end_type);
1011         STASIS_MESSAGE_TYPE_CLEANUP(ast_local_bridge_type);
1012 }
1013
1014 int ast_local_init(void)
1015 {
1016
1017         if (STASIS_MESSAGE_TYPE_INIT(ast_local_optimization_begin_type)) {
1018                 return -1;
1019         }
1020
1021         if (STASIS_MESSAGE_TYPE_INIT(ast_local_optimization_end_type)) {
1022                 return -1;
1023         }
1024
1025         if (STASIS_MESSAGE_TYPE_INIT(ast_local_bridge_type)) {
1026                 return -1;
1027         }
1028
1029         if (!(local_tech.capabilities = ast_format_cap_alloc(0))) {
1030                 return -1;
1031         }
1032         ast_format_cap_add_all(local_tech.capabilities);
1033
1034         locals = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, locals_cmp_cb);
1035         if (!locals) {
1036                 ast_format_cap_destroy(local_tech.capabilities);
1037                 return -1;
1038         }
1039
1040         /* Make sure we can register our channel type */
1041         if (ast_channel_register(&local_tech)) {
1042                 ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n");
1043                 ao2_ref(locals, -1);
1044                 ast_format_cap_destroy(local_tech.capabilities);
1045                 return -1;
1046         }
1047         ast_cli_register_multiple(cli_local, ARRAY_LEN(cli_local));
1048         ast_manager_register_xml_core("LocalOptimizeAway", EVENT_FLAG_SYSTEM|EVENT_FLAG_CALL, manager_optimize_away);
1049
1050         ast_register_atexit(local_shutdown);
1051         return 0;
1052 }