Replace most uses of ast_register_atexit with ast_register_cleanup.
[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_assigned_ids *assignedids, 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_get_latest(ast_channel_uniqueid(p->base.owner));
332         if (!local_one_snapshot) {
333                 return NULL;
334         }
335
336         local_two_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(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         if (!ast_local_optimization_begin_type()) {
361                 return;
362         }
363
364         json_object = ast_json_pack("{s: i, s: i}",
365                         "dest", dest, "id", id);
366
367         if (!json_object) {
368                 return;
369         }
370
371         payload = local_channel_optimization_blob(p, json_object);
372         if (!payload) {
373                 return;
374         }
375
376         if (source) {
377                 RAII_VAR(struct ast_channel_snapshot *, source_snapshot, NULL, ao2_cleanup);
378                 source_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(source));
379                 if (!source_snapshot) {
380                         return;
381                 }
382
383                 ast_multi_channel_blob_add_channel(payload, "source", source_snapshot);
384         }
385
386         msg = stasis_message_create(ast_local_optimization_begin_type(), payload);
387         if (!msg) {
388                 return;
389         }
390
391         stasis_publish(ast_channel_topic(p->base.owner), msg);
392 }
393
394 /*! \brief Callback for \ref ast_unreal_pvt_callbacks \ref optimization_finished_cb */
395 static void local_optimization_finished_cb(struct ast_unreal_pvt *base, int success, unsigned int id)
396 {
397         RAII_VAR(struct ast_json *, json_object, ast_json_null(), ast_json_unref);
398         RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
399         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
400         struct local_pvt *p = (struct local_pvt *)base;
401
402         if (!ast_local_optimization_end_type()) {
403                 return;
404         }
405
406         json_object = ast_json_pack("{s: i, s: i}", "success", success, "id", id);
407
408         if (!json_object) {
409                 return;
410         }
411
412         payload = local_channel_optimization_blob(p, json_object);
413         if (!payload) {
414                 return;
415         }
416
417         msg = stasis_message_create(ast_local_optimization_end_type(), payload);
418         if (!msg) {
419                 return;
420         }
421
422         stasis_publish(ast_channel_topic(p->base.owner), msg);
423 }
424
425 static struct ast_manager_event_blob *local_message_to_ami(struct stasis_message *message)
426 {
427         struct ast_multi_channel_blob *obj = stasis_message_data(message);
428         struct ast_json *blob = ast_multi_channel_blob_get_json(obj);
429         struct ast_channel_snapshot *local_snapshot_one;
430         struct ast_channel_snapshot *local_snapshot_two;
431         RAII_VAR(struct ast_str *, local_channel_one, NULL, ast_free);
432         RAII_VAR(struct ast_str *, local_channel_two, NULL, ast_free);
433         RAII_VAR(struct ast_str *, event_buffer, NULL, ast_free);
434         const char *event;
435
436         local_snapshot_one = ast_multi_channel_blob_get_channel(obj, "1");
437         local_snapshot_two = ast_multi_channel_blob_get_channel(obj, "2");
438         if (!local_snapshot_one || !local_snapshot_two) {
439                 return NULL;
440         }
441
442         event_buffer = ast_str_create(1024);
443         local_channel_one = ast_manager_build_channel_state_string_prefix(local_snapshot_one, "LocalOne");
444         local_channel_two = ast_manager_build_channel_state_string_prefix(local_snapshot_two, "LocalTwo");
445         if (!event_buffer || !local_channel_one || !local_channel_two) {
446                 return NULL;
447         }
448
449         if (stasis_message_type(message) == ast_local_optimization_begin_type()) {
450                 struct ast_channel_snapshot *source_snapshot;
451                 RAII_VAR(struct ast_str *, source_str, NULL, ast_free);
452                 const char *dest_uniqueid;
453
454                 source_snapshot = ast_multi_channel_blob_get_channel(obj, "source");
455                 if (source_snapshot) {
456                         source_str = ast_manager_build_channel_state_string_prefix(source_snapshot, "Source");
457                         if (!source_str) {
458                                 return NULL;
459                         }
460                 }
461
462                 dest_uniqueid = ast_json_object_get(blob, "dest") == AST_UNREAL_OWNER ?
463                                 local_snapshot_one->uniqueid : local_snapshot_two->uniqueid;
464
465                 event = "LocalOptimizationBegin";
466                 if (source_str) {
467                         ast_str_append(&event_buffer, 0, "%s", ast_str_buffer(source_str));
468                 }
469                 ast_str_append(&event_buffer, 0, "DestUniqueId: %s\r\n", dest_uniqueid);
470                 ast_str_append(&event_buffer, 0, "Id: %u\r\n", (unsigned int) ast_json_integer_get(ast_json_object_get(blob, "id")));
471         } else if (stasis_message_type(message) == ast_local_optimization_end_type()) {
472                 event = "LocalOptimizationEnd";
473                 ast_str_append(&event_buffer, 0, "Success: %s\r\n", ast_json_integer_get(ast_json_object_get(blob, "success")) ? "Yes" : "No");
474                 ast_str_append(&event_buffer, 0, "Id: %u\r\n", (unsigned int) ast_json_integer_get(ast_json_object_get(blob, "id")));
475         } else if (stasis_message_type(message) == ast_local_bridge_type()) {
476                 event = "LocalBridge";
477                 ast_str_append(&event_buffer, 0, "Context: %s\r\n", ast_json_string_get(ast_json_object_get(blob, "context")));
478                 ast_str_append(&event_buffer, 0, "Exten: %s\r\n", ast_json_string_get(ast_json_object_get(blob, "exten")));
479                 ast_str_append(&event_buffer, 0, "LocalOptimization: %s\r\n", ast_json_is_true(ast_json_object_get(blob, "can_optimize")) ? "Yes" : "No");
480         } else {
481                 return NULL;
482         }
483
484         return ast_manager_event_blob_create(EVENT_FLAG_CALL, event,
485                 "%s"
486                 "%s"
487                 "%s",
488                 ast_str_buffer(local_channel_one),
489                 ast_str_buffer(local_channel_two),
490                 ast_str_buffer(event_buffer));
491 }
492
493 /*!
494  * \internal
495  * \brief Post the \ref ast_local_bridge_type \ref stasis message
496  * \since 12.0.0
497  *
498  * \param p local_pvt to raise the local bridge message
499  *
500  * \return Nothing
501  */
502 static void publish_local_bridge_message(struct local_pvt *p)
503 {
504         RAII_VAR(struct ast_multi_channel_blob *, multi_blob, NULL, ao2_cleanup);
505         RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
506         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
507         RAII_VAR(struct ast_channel_snapshot *, one_snapshot, NULL, ao2_cleanup);
508         RAII_VAR(struct ast_channel_snapshot *, two_snapshot, NULL, ao2_cleanup);
509         struct ast_channel *owner;
510         struct ast_channel *chan;
511
512         if (!ast_local_bridge_type()) {
513                 return;
514         }
515
516         ast_unreal_lock_all(&p->base, &chan, &owner);
517
518         blob = ast_json_pack("{s: s, s: s, s: b}",
519                 "context", p->context,
520                 "exten", p->exten,
521                 "can_optimize", !ast_test_flag(&p->base, AST_UNREAL_NO_OPTIMIZATION));
522         if (!blob) {
523                 goto end;
524         }
525
526         multi_blob = ast_multi_channel_blob_create(blob);
527         if (!multi_blob) {
528                 goto end;
529         }
530
531         one_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(owner));
532         if (!one_snapshot) {
533                 goto end;
534         }
535
536         two_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan));
537         if (!two_snapshot) {
538                 goto end;
539         }
540
541         ast_multi_channel_blob_add_channel(multi_blob, "1", one_snapshot);
542         ast_multi_channel_blob_add_channel(multi_blob, "2", two_snapshot);
543
544         msg = stasis_message_create(ast_local_bridge_type(), multi_blob);
545         if (!msg) {
546                 goto end;
547         }
548
549         stasis_publish(ast_channel_topic(owner), msg);
550
551 end:
552         ast_channel_unlock(owner);
553         ast_channel_unref(owner);
554
555         ast_channel_unlock(chan);
556         ast_channel_unref(chan);
557
558         ao2_unlock(&p->base);
559 }
560
561 int ast_local_setup_bridge(struct ast_channel *ast, struct ast_bridge *bridge, struct ast_channel *swap, struct ast_bridge_features *features)
562 {
563         struct local_pvt *p;
564         struct local_pvt *found;
565         int res = -1;
566
567         /* Sanity checks. */
568         if (!ast || !bridge) {
569                 ast_bridge_features_destroy(features);
570                 return -1;
571         }
572
573         ast_channel_lock(ast);
574         p = ast_channel_tech_pvt(ast);
575         ast_channel_unlock(ast);
576
577         found = p ? ao2_find(locals, p, 0) : NULL;
578         if (found) {
579                 ao2_lock(found);
580                 if (found->type == LOCAL_CALL_ACTION_DIALPLAN
581                         && found->base.owner
582                         && found->base.chan
583                         && !ast_test_flag(&found->base, AST_UNREAL_CARETAKER_THREAD)) {
584                         ao2_ref(bridge, +1);
585                         if (swap) {
586                                 ast_channel_ref(swap);
587                         }
588                         found->type = LOCAL_CALL_ACTION_BRIDGE;
589                         found->action.bridge.join = bridge;
590                         found->action.bridge.swap = swap;
591                         found->action.bridge.features = features;
592                         res = 0;
593                 } else {
594                         ast_bridge_features_destroy(features);
595                 }
596                 ao2_unlock(found);
597                 ao2_ref(found, -1);
598         }
599
600         return res;
601 }
602
603 int ast_local_setup_masquerade(struct ast_channel *ast, struct ast_channel *masq)
604 {
605         struct local_pvt *p;
606         struct local_pvt *found;
607         int res = -1;
608
609         /* Sanity checks. */
610         if (!ast || !masq) {
611                 return -1;
612         }
613
614         ast_channel_lock(ast);
615         p = ast_channel_tech_pvt(ast);
616         ast_channel_unlock(ast);
617
618         found = p ? ao2_find(locals, p, 0) : NULL;
619         if (found) {
620                 ao2_lock(found);
621                 if (found->type == LOCAL_CALL_ACTION_DIALPLAN
622                         && found->base.owner
623                         && found->base.chan
624                         && !ast_test_flag(&found->base, AST_UNREAL_CARETAKER_THREAD)) {
625                         ast_channel_ref(masq);
626                         found->type = LOCAL_CALL_ACTION_MASQUERADE;
627                         found->action.masq = masq;
628                         res = 0;
629                 }
630                 ao2_unlock(found);
631                 ao2_ref(found, -1);
632         }
633
634         return res;
635 }
636
637 /*! \brief Initiate new call, part of PBX interface
638  *         dest is the dial string */
639 static int local_call(struct ast_channel *ast, const char *dest, int timeout)
640 {
641         struct local_pvt *p = ast_channel_tech_pvt(ast);
642         int pvt_locked = 0;
643
644         struct ast_channel *owner = NULL;
645         struct ast_channel *chan = NULL;
646         int res;
647         char *reduced_dest = ast_strdupa(dest);
648         char *slash;
649         const char *chan_cid;
650
651         if (!p) {
652                 return -1;
653         }
654
655         /* since we are letting go of channel locks that were locked coming into
656          * this function, then we need to give the tech pvt a ref */
657         ao2_ref(p, 1);
658         ast_channel_unlock(ast);
659
660         ast_unreal_lock_all(&p->base, &chan, &owner);
661         pvt_locked = 1;
662
663         if (owner != ast) {
664                 res = -1;
665                 goto return_cleanup;
666         }
667
668         if (!owner || !chan) {
669                 res = -1;
670                 goto return_cleanup;
671         }
672
673         ast_unreal_call_setup(owner, chan);
674
675         /*
676          * If the local channel has /n on the end of it, we need to lop
677          * that off for our argument to setting up the CC_INTERFACES
678          * variable.
679          */
680         if ((slash = strrchr(reduced_dest, '/'))) {
681                 *slash = '\0';
682         }
683         ast_set_cc_interfaces_chanvar(chan, reduced_dest);
684
685         ao2_unlock(p);
686         pvt_locked = 0;
687
688         ast_channel_unlock(owner);
689
690         chan_cid = S_COR(ast_channel_caller(chan)->id.number.valid,
691                 ast_channel_caller(chan)->id.number.str, NULL);
692         if (chan_cid) {
693                 chan_cid = ast_strdupa(chan_cid);
694         }
695         ast_channel_unlock(chan);
696
697         res = -1;
698         switch (p->type) {
699         case LOCAL_CALL_ACTION_DIALPLAN:
700                 if (!ast_exists_extension(NULL, p->context, p->exten, 1, chan_cid)) {
701                         ast_log(LOG_NOTICE, "No such extension/context %s@%s while calling Local channel\n",
702                                 p->exten, p->context);
703                 } else {
704                         publish_local_bridge_message(p);
705
706                         /* Start switch on sub channel */
707                         res = ast_pbx_start(chan);
708                 }
709                 break;
710         case LOCAL_CALL_ACTION_BRIDGE:
711                 publish_local_bridge_message(p);
712                 ast_answer(chan);
713                 res = ast_bridge_impart(p->action.bridge.join, chan, p->action.bridge.swap,
714                         p->action.bridge.features, AST_BRIDGE_IMPART_CHAN_INDEPENDENT);
715                 ao2_ref(p->action.bridge.join, -1);
716                 p->action.bridge.join = NULL;
717                 ao2_cleanup(p->action.bridge.swap);
718                 p->action.bridge.swap = NULL;
719                 p->action.bridge.features = NULL;
720                 break;
721         case LOCAL_CALL_ACTION_MASQUERADE:
722                 publish_local_bridge_message(p);
723                 ast_answer(chan);
724                 res = ast_channel_move(p->action.masq, chan);
725                 if (!res) {
726                         /* Chan is now an orphaned zombie.  Destroy it. */
727                         ast_hangup(chan);
728                 }
729                 p->action.masq = ast_channel_unref(p->action.masq);
730                 break;
731         }
732         if (!res) {
733                 ao2_lock(p);
734                 ast_set_flag(&p->base, AST_UNREAL_CARETAKER_THREAD);
735                 ao2_unlock(p);
736         }
737
738         /* we already unlocked them, clear them here so the cleanup label won't touch them. */
739         owner = ast_channel_unref(owner);
740         chan = ast_channel_unref(chan);
741
742 return_cleanup:
743         if (p) {
744                 if (pvt_locked) {
745                         ao2_unlock(p);
746                 }
747                 ao2_ref(p, -1);
748         }
749         if (chan) {
750                 ast_channel_unlock(chan);
751                 ast_channel_unref(chan);
752         }
753
754         /*
755          * owner is supposed to be == to ast, if it is, don't unlock it
756          * because ast must exit locked
757          */
758         if (owner) {
759                 if (owner != ast) {
760                         ast_channel_unlock(owner);
761                         ast_channel_lock(ast);
762                 }
763                 ast_channel_unref(owner);
764         } else {
765                 /* we have to exit with ast locked */
766                 ast_channel_lock(ast);
767         }
768
769         return res;
770 }
771
772 /*! \brief Hangup a call through the local proxy channel */
773 static int local_hangup(struct ast_channel *ast)
774 {
775         struct local_pvt *p = ast_channel_tech_pvt(ast);
776         int res;
777
778         if (!p) {
779                 return -1;
780         }
781
782         /* give the pvt a ref to fulfill calling requirements. */
783         ao2_ref(p, +1);
784         res = ast_unreal_hangup(&p->base, ast);
785         if (!res) {
786                 int unlink;
787
788                 ao2_lock(p);
789                 unlink = !p->base.owner && !p->base.chan;
790                 ao2_unlock(p);
791                 if (unlink) {
792                         ao2_unlink(locals, p);
793                 }
794         }
795         ao2_ref(p, -1);
796
797         return res;
798 }
799
800 /*!
801  * \internal
802  * \brief struct local_pvt destructor.
803  *
804  * \param vdoomed Object to destroy.
805  *
806  * \return Nothing
807  */
808 static void local_pvt_destructor(void *vdoomed)
809 {
810         struct local_pvt *doomed = vdoomed;
811
812         switch (doomed->type) {
813         case LOCAL_CALL_ACTION_DIALPLAN:
814                 break;
815         case LOCAL_CALL_ACTION_BRIDGE:
816                 ao2_cleanup(doomed->action.bridge.join);
817                 ao2_cleanup(doomed->action.bridge.swap);
818                 ast_bridge_features_destroy(doomed->action.bridge.features);
819                 break;
820         case LOCAL_CALL_ACTION_MASQUERADE:
821                 ao2_cleanup(doomed->action.masq);
822                 break;
823         }
824         ast_unreal_destructor(&doomed->base);
825 }
826
827 /*! \brief Create a call structure */
828 static struct local_pvt *local_alloc(const char *data, struct ast_format_cap *cap)
829 {
830         struct local_pvt *pvt;
831         char *parse;
832         char *context;
833         char *opts;
834
835         pvt = (struct local_pvt *) ast_unreal_alloc(sizeof(*pvt), local_pvt_destructor, cap);
836         if (!pvt) {
837                 return NULL;
838         }
839         pvt->base.callbacks = &local_unreal_callbacks;
840
841         parse = ast_strdupa(data);
842
843         /*
844          * Local channels intercept MOH by default.
845          *
846          * This is a silly default because it represents state held by
847          * the local channels.  Unless local channel optimization is
848          * disabled, the state will dissapear when the local channels
849          * optimize out.
850          */
851         ast_set_flag(&pvt->base, AST_UNREAL_MOH_INTERCEPT);
852
853         /* Look for options */
854         if ((opts = strchr(parse, '/'))) {
855                 *opts++ = '\0';
856                 if (strchr(opts, 'n')) {
857                         ast_set_flag(&pvt->base, AST_UNREAL_NO_OPTIMIZATION);
858                 }
859                 if (strchr(opts, 'j')) {
860                         if (ast_test_flag(&pvt->base, AST_UNREAL_NO_OPTIMIZATION)) {
861                                 ast_set_flag(&pvt->base.jb_conf, AST_JB_ENABLED);
862                         } else {
863                                 ast_log(LOG_ERROR, "You must use the 'n' option with the 'j' option to enable the jitter buffer\n");
864                         }
865                 }
866                 if (strchr(opts, 'm')) {
867                         ast_clear_flag(&pvt->base, AST_UNREAL_MOH_INTERCEPT);
868                 }
869         }
870
871         /* Look for a context */
872         if ((context = strchr(parse, '@'))) {
873                 *context++ = '\0';
874         }
875
876         ast_copy_string(pvt->context, S_OR(context, "default"), sizeof(pvt->context));
877         ast_copy_string(pvt->exten, parse, sizeof(pvt->exten));
878         snprintf(pvt->base.name, sizeof(pvt->base.name), "%s@%s", pvt->exten, pvt->context);
879
880         return pvt; /* this is returned with a ref */
881 }
882
883 /*! \brief Part of PBX interface */
884 static struct ast_channel *local_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
885 {
886         struct local_pvt *p;
887         struct ast_channel *chan;
888         ast_callid callid;
889
890         /* Allocate a new private structure and then Asterisk channels */
891         p = local_alloc(data, cap);
892         if (!p) {
893                 return NULL;
894         }
895         callid = ast_read_threadstorage_callid();
896         chan = ast_unreal_new_channels(&p->base, &local_tech, AST_STATE_DOWN, AST_STATE_RING,
897                 p->exten, p->context, assignedids, requestor, callid);
898         if (chan) {
899                 ao2_link(locals, p);
900         }
901         ao2_ref(p, -1); /* kill the ref from the alloc */
902
903         return chan;
904 }
905
906 /*! \brief CLI command "local show channels" */
907 static char *locals_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
908 {
909         struct local_pvt *p;
910         struct ao2_iterator it;
911
912         switch (cmd) {
913         case CLI_INIT:
914                 e->command = "local show channels";
915                 e->usage =
916                         "Usage: local show channels\n"
917                         "       Provides summary information on active local proxy channels.\n";
918                 return NULL;
919         case CLI_GENERATE:
920                 return NULL;
921         }
922
923         if (a->argc != 3) {
924                 return CLI_SHOWUSAGE;
925         }
926
927         if (ao2_container_count(locals) == 0) {
928                 ast_cli(a->fd, "No local channels in use\n");
929                 return RESULT_SUCCESS;
930         }
931
932         it = ao2_iterator_init(locals, 0);
933         while ((p = ao2_iterator_next(&it))) {
934                 ao2_lock(p);
935                 ast_cli(a->fd, "%s -- %s\n",
936                         p->base.owner ? ast_channel_name(p->base.owner) : "<unowned>",
937                         p->base.name);
938                 ao2_unlock(p);
939                 ao2_ref(p, -1);
940         }
941         ao2_iterator_destroy(&it);
942
943         return CLI_SUCCESS;
944 }
945
946 static struct ast_cli_entry cli_local[] = {
947         AST_CLI_DEFINE(locals_show, "List status of local channels"),
948 };
949
950 static int manager_optimize_away(struct mansession *s, const struct message *m)
951 {
952         const char *channel;
953         struct local_pvt *p;
954         struct local_pvt *found;
955         struct ast_channel *chan;
956
957         channel = astman_get_header(m, "Channel");
958         if (ast_strlen_zero(channel)) {
959                 astman_send_error(s, m, "'Channel' not specified.");
960                 return 0;
961         }
962
963         chan = ast_channel_get_by_name(channel);
964         if (!chan) {
965                 astman_send_error(s, m, "Channel does not exist.");
966                 return 0;
967         }
968
969         p = ast_channel_tech_pvt(chan);
970         ast_channel_unref(chan);
971
972         found = p ? ao2_find(locals, p, 0) : NULL;
973         if (found) {
974                 ao2_lock(found);
975                 ast_clear_flag(&found->base, AST_UNREAL_NO_OPTIMIZATION);
976                 ao2_unlock(found);
977                 ao2_ref(found, -1);
978                 astman_send_ack(s, m, "Queued channel to be optimized away");
979         } else {
980                 astman_send_error(s, m, "Unable to find channel");
981         }
982
983         return 0;
984 }
985
986
987 static int locals_cmp_cb(void *obj, void *arg, int flags)
988 {
989         return (obj == arg) ? CMP_MATCH : 0;
990 }
991
992 /*!
993  * \internal
994  * \brief Shutdown the local proxy channel.
995  * \since 12.0.0
996  *
997  * \return Nothing
998  */
999 static void local_shutdown(void)
1000 {
1001         struct local_pvt *p;
1002         struct ao2_iterator it;
1003
1004         /* First, take us out of the channel loop */
1005         ast_cli_unregister_multiple(cli_local, ARRAY_LEN(cli_local));
1006         ast_manager_unregister("LocalOptimizeAway");
1007         ast_channel_unregister(&local_tech);
1008
1009         ao2_ref(locals, -1);
1010         locals = NULL;
1011
1012         ao2_cleanup(local_tech.capabilities);
1013         local_tech.capabilities = NULL;
1014
1015         STASIS_MESSAGE_TYPE_CLEANUP(ast_local_optimization_begin_type);
1016         STASIS_MESSAGE_TYPE_CLEANUP(ast_local_optimization_end_type);
1017         STASIS_MESSAGE_TYPE_CLEANUP(ast_local_bridge_type);
1018 }
1019
1020 int ast_local_init(void)
1021 {
1022
1023         if (STASIS_MESSAGE_TYPE_INIT(ast_local_optimization_begin_type)) {
1024                 return -1;
1025         }
1026
1027         if (STASIS_MESSAGE_TYPE_INIT(ast_local_optimization_end_type)) {
1028                 return -1;
1029         }
1030
1031         if (STASIS_MESSAGE_TYPE_INIT(ast_local_bridge_type)) {
1032                 return -1;
1033         }
1034
1035         if (!(local_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
1036                 return -1;
1037         }
1038         ast_format_cap_append_by_type(local_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
1039
1040         locals = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, locals_cmp_cb);
1041         if (!locals) {
1042                 ao2_cleanup(local_tech.capabilities);
1043                 local_tech.capabilities = NULL;
1044                 return -1;
1045         }
1046
1047         /* Make sure we can register our channel type */
1048         if (ast_channel_register(&local_tech)) {
1049                 ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n");
1050                 ao2_ref(locals, -1);
1051                 ao2_cleanup(local_tech.capabilities);
1052                 local_tech.capabilities = NULL;
1053                 return -1;
1054         }
1055         ast_cli_register_multiple(cli_local, ARRAY_LEN(cli_local));
1056         ast_manager_register_xml_core("LocalOptimizeAway", EVENT_FLAG_SYSTEM|EVENT_FLAG_CALL, manager_optimize_away);
1057
1058         ast_register_cleanup(local_shutdown);
1059         return 0;
1060 }