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