Asterisk - The Open Source Telephony Project GIT-master-d856a3e
parking_manager.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2013, Digium, Inc.
5 *
6 * Jonathan Rose <jrose@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/*! \file
20 *
21 * \brief Call Parking Manager Actions and Events
22 *
23 * \author Jonathan Rose <jrose@digium.com>
24 */
25
26#include "asterisk.h"
27
28#include "res_parking.h"
29#include "asterisk/config.h"
31#include "asterisk/utils.h"
32#include "asterisk/module.h"
33#include "asterisk/cli.h"
34#include "asterisk/astobj2.h"
35#include "asterisk/features.h"
36#include "asterisk/manager.h"
37#include "asterisk/bridge.h"
38#include "asterisk/module.h"
39
40/*** DOCUMENTATION
41 <manager name="Parkinglots" language="en_US">
42 <synopsis>
43 Get a list of parking lots
44 </synopsis>
45 <syntax>
46 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
47 </syntax>
48 <description>
49 <para>List all parking lots as a series of AMI events</para>
50 </description>
51 </manager>
52 <manager name="ParkedCalls" language="en_US">
53 <synopsis>
54 List parked calls.
55 </synopsis>
56 <syntax>
57 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
58 <parameter name="ParkingLot">
59 <para>If specified, only show parked calls from the parking lot with this name.</para>
60 </parameter>
61 </syntax>
62 <description>
63 <para>List parked calls.</para>
64 </description>
65 </manager>
66 <manager name="Park" language="en_US">
67 <synopsis>
68 Park a channel.
69 </synopsis>
70 <syntax>
71 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
72 <parameter name="Channel" required="true">
73 <para>Channel name to park.</para>
74 </parameter>
75 <parameter name="TimeoutChannel" required="false">
76 <para>Channel name to use when constructing the dial string that will be dialed if the parked channel
77 times out. If <literal>TimeoutChannel</literal> is in a two party bridge with
78 <literal>Channel</literal>, then <literal>TimeoutChannel</literal> will receive an announcement and be
79 treated as having parked <literal>Channel</literal> in the same manner as the Park Call DTMF feature.
80 </para>
81 </parameter>
82 <parameter name="AnnounceChannel" required="false">
83 <para>If specified, then this channel will receive an announcement when <literal>Channel</literal>
84 is parked if <literal>AnnounceChannel</literal> is in a state where it can receive announcements
85 (AnnounceChannel must be bridged). <literal>AnnounceChannel</literal> has no bearing on the actual
86 state of the parked call.</para>
87 </parameter>
88 <parameter name="Timeout" required="false">
89 <para>Overrides the timeout of the parking lot for this park action. Specified in milliseconds, but will be converted to
90 seconds. Use a value of 0 to disable the timeout.
91 </para>
92 </parameter>
93 <parameter name="Parkinglot" required="false">
94 <para>The parking lot to use when parking the channel</para>
95 </parameter>
96 <parameter name="ParkingSpace" required="false">
97 <para>The parking space extension in the parking lot.
98 If the space is already in use then execution will continue at the next priority.
99 </para>
100 </parameter>
101 </syntax>
102 <description>
103 <para>Park an arbitrary channel with optional arguments for specifying the parking lot used, how long
104 the channel should remain parked, and what dial string to use as the parker if the call times out.
105 </para>
106 </description>
107 </manager>
108 <managerEvent language="en_US" name="ParkedCall">
109 <managerEventInstance class="EVENT_FLAG_CALL">
110 <synopsis>Raised when a channel is parked.</synopsis>
111 <syntax>
112 <channel_snapshot prefix="Parkee"/>
113 <parameter name="ParkerDialString">
114 <para>Dial String that can be used to call back the parker on ParkingTimeout.</para>
115 </parameter>
116 <parameter name="Parkinglot">
117 <para>Name of the parking lot that the parkee is parked in</para>
118 </parameter>
119 <parameter name="ParkingSpace">
120 <para>Parking Space that the parkee is parked in</para>
121 </parameter>
122 <parameter name="ParkingTimeout">
123 <para>Time remaining until the parkee is forcefully removed from parking in seconds</para>
124 </parameter>
125 <parameter name="ParkingDuration">
126 <para>Time the parkee has been in the parking bridge (in seconds)</para>
127 </parameter>
128 </syntax>
129 </managerEventInstance>
130 </managerEvent>
131 <managerEvent language="en_US" name="ParkedCallTimeOut">
132 <managerEventInstance class="EVENT_FLAG_CALL">
133 <synopsis>Raised when a channel leaves a parking lot due to reaching the time limit of being parked.</synopsis>
134 <syntax>
135 <channel_snapshot prefix="Parkee"/>
136 <channel_snapshot prefix="Parker"/>
137 <xi:include xpointer="xpointer(/docs/managerEvent[@name='ParkedCall']/managerEventInstance/syntax/parameter)" />
138 </syntax>
139 </managerEventInstance>
140 </managerEvent>
141 <managerEvent language="en_US" name="ParkedCallGiveUp">
142 <managerEventInstance class="EVENT_FLAG_CALL">
143 <synopsis>Raised when a channel leaves a parking lot because it hung up without being answered.</synopsis>
144 <syntax>
145 <channel_snapshot prefix="Parkee"/>
146 <channel_snapshot prefix="Parker"/>
147 <xi:include xpointer="xpointer(/docs/managerEvent[@name='ParkedCall']/managerEventInstance/syntax/parameter)" />
148 </syntax>
149 </managerEventInstance>
150 </managerEvent>
151 <managerEvent language="en_US" name="UnParkedCall">
152 <managerEventInstance class="EVENT_FLAG_CALL">
153 <synopsis>Raised when a channel leaves a parking lot because it was retrieved from the parking lot and reconnected.</synopsis>
154 <syntax>
155 <channel_snapshot prefix="Parkee"/>
156 <channel_snapshot prefix="Parker"/>
157 <xi:include xpointer="xpointer(/docs/managerEvent[@name='ParkedCall']/managerEventInstance/syntax/parameter)" />
158 <channel_snapshot prefix="Retriever"/>
159 </syntax>
160 </managerEventInstance>
161 </managerEvent>
162 <managerEvent language="en_US" name="ParkedCallSwap">
163 <managerEventInstance class="EVENT_FLAG_CALL">
164 <synopsis>Raised when a channel takes the place of a previously parked channel</synopsis>
165 <syntax>
166 <channel_snapshot prefix="Parkee"/>
167 <channel_snapshot prefix="Parker"/>
168 <xi:include xpointer="xpointer(/docs/managerEvent[@name='ParkedCall']/managerEventInstance/syntax/parameter)" />
169 </syntax>
170 <description>
171 <para>This event is raised when a channel initially parked in the parking lot
172 is swapped out with a different channel. The most common case for this is when
173 an attended transfer to a parking lot occurs. The Parkee information in the event
174 will indicate the party that was swapped into the parking lot.</para>
175 </description>
176 </managerEventInstance>
177 </managerEvent>
178 ***/
179
180/*! \brief subscription to the parking lot topic */
182
184{
185 RAII_VAR(struct ast_channel_snapshot *, parkee_snapshot, NULL, ao2_cleanup);
186
187 ast_channel_lock(chan);
188 parkee_snapshot = ast_channel_snapshot_create(chan);
189 ast_channel_unlock(chan);
190 if (!parkee_snapshot) {
191 return NULL;
192 }
193
194 return ast_parked_call_payload_create(PARKED_CALL_FAILED, parkee_snapshot, NULL, NULL, NULL, 0, 0, 0);
195}
196
198{
199 RAII_VAR(struct ast_channel_snapshot *, parkee_snapshot, NULL, ao2_cleanup);
200 long int timeout;
201 long int duration;
202 struct timeval now = ast_tvnow();
203 const char *lot_name = pu->lot->name;
204
206 parkee_snapshot = ast_channel_snapshot_create(pu->chan);
208 if (!parkee_snapshot) {
209 return NULL;
210 }
211
212 timeout = pu->start.tv_sec + (long) pu->time_limit - now.tv_sec;
213 duration = now.tv_sec - pu->start.tv_sec;
214
215 return ast_parked_call_payload_create(event_type, parkee_snapshot, pu->parker_dial_string, pu->retriever, lot_name, pu->parking_space, timeout, duration);
216
217}
218
219/*! \brief Builds a manager string based on the contents of a parked call payload */
221{
222 struct ast_str *out = ast_str_create(1024);
223 RAII_VAR(struct ast_str *, parkee_string, NULL, ast_free);
224 RAII_VAR(struct ast_str *, retriever_string, NULL, ast_free);
225
226 if (!out) {
227 return NULL;
228 }
229
230 parkee_string = ast_manager_build_channel_state_string_prefix(payload->parkee, "Parkee");
231 if (!parkee_string) {
232 ast_free(out);
233 return NULL;
234 }
235
236 if (payload->retriever) {
237 retriever_string = ast_manager_build_channel_state_string_prefix(payload->retriever, "Retriever");
238 if (!retriever_string) {
239 ast_free(out);
240 return NULL;
241 }
242 }
243
244 ast_str_set(&out, 0,
245 "%s" /* parkee channel state */
246 "%s" /* retriever channel state (when available) */
247 "ParkerDialString: %s\r\n"
248 "Parkinglot: %s\r\n"
249 "ParkingSpace: %u\r\n"
250 "ParkingTimeout: %lu\r\n"
251 "ParkingDuration: %lu\r\n",
252
253 ast_str_buffer(parkee_string),
254 retriever_string ? ast_str_buffer(retriever_string) : "",
255 payload->parker_dial_string,
256 payload->parkinglot,
257 payload->parkingspace,
258 payload->timeout,
259 payload->duration);
260
261 return out;
262}
263
264static void manager_parking_status_single_lot(struct mansession *s, const struct message *m, const char *id_text, const char *lot_name)
265{
266 RAII_VAR(struct parking_lot *, curlot, NULL, ao2_cleanup);
267 struct parked_user *curuser;
268 struct ao2_iterator iter_users;
269 int total = 0;
270
271 curlot = parking_lot_find_by_name(lot_name);
272 if (!curlot) {
273 astman_send_error(s, m, "Requested parking lot could not be found.");
274 return;
275 }
276
277 astman_send_listack(s, m, "Parked calls will follow", "start");
278
279 iter_users = ao2_iterator_init(curlot->parked_users, 0);
280 while ((curuser = ao2_iterator_next(&iter_users))) {
282 RAII_VAR(struct ast_str *, parked_call_string, NULL, ast_free);
283
285 if (!payload) {
286 ao2_ref(curuser, -1);
287 break;
288 }
289
290 parked_call_string = manager_build_parked_call_string(payload);
291 if (!parked_call_string) {
292 ao2_ref(curuser, -1);
293 break;
294 }
295
296 total++;
297
298 astman_append(s, "Event: ParkedCall\r\n"
299 "%s" /* The parked call string */
300 "%s" /* The action ID */
301 "\r\n",
302 ast_str_buffer(parked_call_string),
303 id_text);
304
305 ao2_ref(curuser, -1);
306 }
307 ao2_iterator_destroy(&iter_users);
308
309 astman_send_list_complete_start(s, m, "ParkedCallsComplete", total);
310 astman_append(s, "Total: %d\r\n", total);
312}
313
314static void manager_parking_status_all_lots(struct mansession *s, const struct message *m, const char *id_text)
315{
316 struct parked_user *curuser;
317 struct ao2_container *lot_container;
318 struct ao2_iterator iter_lots;
319 struct ao2_iterator iter_users;
320 struct parking_lot *curlot;
321 int total = 0;
322
323 lot_container = get_parking_lot_container();
324 if (!lot_container) {
325 ast_log(LOG_ERROR, "Failed to obtain parking lot list. Action canceled.\n");
326 astman_send_error(s, m, "Could not create parking lot list");
327 return;
328 }
329
330 astman_send_listack(s, m, "Parked calls will follow", "start");
331
332 iter_lots = ao2_iterator_init(lot_container, 0);
333 while ((curlot = ao2_iterator_next(&iter_lots))) {
334 iter_users = ao2_iterator_init(curlot->parked_users, 0);
335 while ((curuser = ao2_iterator_next(&iter_users))) {
337 RAII_VAR(struct ast_str *, parked_call_string, NULL, ast_free);
338
340 if (!payload) {
341 ao2_ref(curuser, -1);
342 ao2_iterator_destroy(&iter_users);
343 ao2_ref(curlot, -1);
344 goto abort_list;
345 }
346
347 parked_call_string = manager_build_parked_call_string(payload);
348 if (!parked_call_string) {
349 ao2_ref(curuser, -1);
350 ao2_iterator_destroy(&iter_users);
351 ao2_ref(curlot, -1);
352 goto abort_list;
353 }
354
355 total++;
356
357 astman_append(s, "Event: ParkedCall\r\n"
358 "%s" /* The parked call string */
359 "%s" /* The action ID */
360 "\r\n",
361 ast_str_buffer(parked_call_string),
362 id_text);
363
364 ao2_ref(curuser, -1);
365 }
366 ao2_iterator_destroy(&iter_users);
367 ao2_ref(curlot, -1);
368 }
369abort_list:
370 ao2_iterator_destroy(&iter_lots);
371
372 astman_send_list_complete_start(s, m, "ParkedCallsComplete", total);
373 astman_append(s, "Total: %d\r\n", total);
375}
376
377static int manager_parking_status(struct mansession *s, const struct message *m)
378{
379 const char *id = astman_get_header(m, "ActionID");
380 const char *lot_name = astman_get_header(m, "ParkingLot");
381 char id_text[256];
382
383 id_text[0] = '\0';
384 if (!ast_strlen_zero(id)) {
385 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
386 }
387
388 if (!ast_strlen_zero(lot_name)) {
389 manager_parking_status_single_lot(s, m, id_text, lot_name);
390 } else {
391 manager_parking_status_all_lots(s, m, id_text);
392 }
393
394 return 0;
395}
396
398 const char *id_text;
399 int count;
400};
401
402static int manager_append_event_parking_lot_data_cb(void *obj, void *arg, void *data, int flags)
403{
404 struct parking_lot *curlot = obj;
405 struct mansession *s = arg;
406 struct park_list_data *list_data = data;
407
408 astman_append(s, "Event: Parkinglot\r\n"
409 "%s" /* The Action ID */
410 "Name: %s\r\n"
411 "StartSpace: %d\r\n"
412 "StopSpace: %d\r\n"
413 "Timeout: %u\r\n"
414 "\r\n",
415 list_data->id_text,
416 curlot->name,
417 curlot->cfg->parking_start,
418 curlot->cfg->parking_stop,
419 curlot->cfg->parkingtime);
420 ++list_data->count;
421
422 return 0;
423}
424
425static int manager_parking_lot_list(struct mansession *s, const struct message *m)
426{
427 const char *id = astman_get_header(m, "ActionID");
428 struct ao2_container *lot_container;
429 char id_text[256];
430 struct park_list_data list_data;
431
432 id_text[0] = '\0';
433 if (!ast_strlen_zero(id)) {
434 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
435 }
436
437 lot_container = get_parking_lot_container();
438 if (!lot_container) {
439 ast_log(LOG_ERROR, "Failed to obtain parking lot list. Action canceled.\n");
440 astman_send_error(s, m, "Could not create parking lot list");
441 return 0;
442 }
443
444 astman_send_listack(s, m, "Parking lots will follow", "start");
445
446 list_data.id_text = id_text;
447 list_data.count = 0;
450
451 astman_send_list_complete_start(s, m, "ParkinglotsComplete", list_data.count);
453
454 return 0;
455}
456
457static void manager_park_unbridged(struct mansession *s, const struct message *m,
458 struct ast_channel *chan, const char *parkinglot, int timeout_override)
459{
460 struct ast_bridge *parking_bridge = park_common_setup(chan,
461 chan, parkinglot, NULL, 0, 0, timeout_override, 1);
462
463 if (!parking_bridge) {
464 astman_send_error(s, m, "Park action failed\n");
465 return;
466 }
467
468 if (ast_bridge_add_channel(parking_bridge, chan, NULL, 0, NULL)) {
469 astman_send_error(s, m, "Park action failed\n");
470 ao2_cleanup(parking_bridge);
471 return;
472 }
473
474 astman_send_ack(s, m, "Park successful\n");
475 ao2_cleanup(parking_bridge);
476}
477
478static void manager_park_bridged(struct mansession *s, const struct message *m,
479 struct ast_channel *chan, struct ast_channel *parker_chan,
480 const char *parkinglot, int timeout_override)
481{
482 struct ast_bridge_channel *bridge_channel;
483 char *app_data;
484
485 if (timeout_override != -1) {
486 if (ast_asprintf(&app_data, "%s,t(%d)", parkinglot, timeout_override) == -1) {
487 astman_send_error(s, m, "Park action failed\n");
488 return;
489 }
490 } else {
491 if (ast_asprintf(&app_data, "%s", parkinglot) == -1) {
492 astman_send_error(s, m, "Park action failed\n");
493 return;
494 }
495 }
496
497 ast_channel_lock(parker_chan);
498 bridge_channel = ast_channel_get_bridge_channel(parker_chan);
499 ast_channel_unlock(parker_chan);
500
501 if (!bridge_channel) {
503 astman_send_error(s, m, "Park action failed\n");
504 return;
505 }
506
507 /* Subscribe to park messages for the channel being parked */
510 astman_send_error(s, m, "Park action failed\n");
511 ao2_cleanup(bridge_channel);
512 return;
513 }
514
516 ast_channel_uniqueid(parker_chan), app_data);
517
519
520 astman_send_ack(s, m, "Park successful\n");
521 ao2_cleanup(bridge_channel);
522}
523
524static int manager_park(struct mansession *s, const struct message *m)
525{
526 const char *channel = astman_get_header(m, "Channel");
527 const char *timeout_channel = S_OR(astman_get_header(m, "TimeoutChannel"), astman_get_header(m, "Channel2"));
528 const char *announce_channel = astman_get_header(m, "AnnounceChannel");
529 const char *timeout = astman_get_header(m, "Timeout");
530 const char *parkinglot = astman_get_header(m, "Parkinglot");
531 const char *parkingspace = astman_get_header(m, "ParkingSpace");
532 char buf[BUFSIZ];
533 int timeout_override = -1;
534
535 RAII_VAR(struct ast_channel *, parker_chan, NULL, ao2_cleanup);
537
538 if (ast_strlen_zero(channel)) {
539 astman_send_error(s, m, "Channel not specified");
540 return 0;
541 }
542
543 if (!ast_strlen_zero(timeout)) {
544 if (sscanf(timeout, "%30d", &timeout_override) != 1 || timeout_override < 0) {
545 astman_send_error(s, m, "Invalid Timeout value.");
546 return 0;
547 }
548
549 if (timeout_override) {
550 /* If greater than zero, convert to seconds for internal use. Must be >= 1 second. */
551 timeout_override = MAX(1, timeout_override / 1000);
552 }
553 }
554
555 if (!(chan = ast_channel_get_by_name(channel))) {
556 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
557 astman_send_error(s, m, buf);
558 return 0;
559 }
560
561 if (!ast_strlen_zero(timeout_channel)) {
563 ast_bridge_set_transfer_variables(chan, timeout_channel, 0);
565 }
566
567 if (!ast_strlen_zero(parkingspace)) {
568 pbx_builtin_setvar_helper(chan, "PARKINGEXTEN", parkingspace);
569 }
570
571 parker_chan = ast_channel_bridge_peer(chan);
572 if (!parker_chan || strcmp(ast_channel_name(parker_chan), timeout_channel)) {
573 if (!ast_strlen_zero(announce_channel)) {
574 struct ast_channel *announce_chan = ast_channel_get_by_name(announce_channel);
575 if (!announce_channel) {
576 astman_send_error(s, m, "AnnounceChannel does not exist");
577 return 0;
578 }
579
580 create_parked_subscription(announce_chan, ast_channel_uniqueid(chan), 0);
581 ast_channel_cleanup(announce_chan);
582 }
583
584 manager_park_unbridged(s, m, chan, parkinglot, timeout_override);
585 return 0;
586 }
587
588 if (!ast_strlen_zero(announce_channel) && strcmp(announce_channel, timeout_channel)) {
589 /* When using an announce_channel in bridge mode, only add the announce channel if it isn't
590 * the same as the timeout channel (which will play announcements anyway) */
591 struct ast_channel *announce_chan = ast_channel_get_by_name(announce_channel);
592 if (!announce_channel) {
593 astman_send_error(s, m, "AnnounceChannel does not exist");
594 return 0;
595 }
596
597 create_parked_subscription(announce_chan, ast_channel_uniqueid(chan), 0);
598 ast_channel_cleanup(announce_chan);
599 }
600
601 manager_park_bridged(s, m, chan, parker_chan, parkinglot, timeout_override);
602 return 0;
603}
604
606{
608 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
609
610 if (!ast_parked_call_type()) {
611 return;
612 }
613
614 payload = parked_call_payload_from_failure(parkee);
615 if (!payload) {
616 return;
617 }
618
620 if (!msg) {
621 return;
622 }
623
625}
626
628{
630 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
631
632 if (!ast_parked_call_type()) {
633 return;
634 }
635
636 payload = parked_call_payload_from_parked_user(pu, event_type);
637 if (!payload) {
638 return;
639 }
640
642 if (!msg) {
643 return;
644 }
645
647}
648
650{
651 char *event_type = "";
652 RAII_VAR(struct ast_str *, parked_call_string, NULL, ast_free);
653
654 switch (parked_call->event_type) {
655 case PARKED_CALL:
656 event_type = "ParkedCall";
657 break;
659 event_type = "ParkedCallTimeOut";
660 break;
662 event_type = "ParkedCallGiveUp";
663 break;
665 event_type = "UnParkedCall";
666 break;
667 case PARKED_CALL_SWAP:
668 event_type = "ParkedCallSwap";
669 break;
671 /* PARKED_CALL_FAILED doesn't currently get a message and is used exclusively for bridging */
672 return;
673 }
674
675 parked_call_string = manager_build_parked_call_string(parked_call);
676 if (!parked_call_string) {
677 ast_log(LOG_ERROR, "Failed to issue an AMI event of '%s' in response to a stasis message.\n", event_type);
678 return;
679 }
680
681 manager_event(EVENT_FLAG_CALL, event_type,
682 "%s",
683 ast_str_buffer(parked_call_string)
684 );
685}
686
688{
690 struct ast_parked_call_payload *parked_call_message = stasis_message_data(message);
691 parked_call_message_response(parked_call_message);
692 }
693}
694
696{
697 if (!parking_sub) {
701 }
702}
703
705{
706 int res;
707
712 return res ? -1 : 0;
713}
714
716{
718}
719
721{
722 ast_manager_unregister("Parkinglots");
723 ast_manager_unregister("ParkedCalls");
726}
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define ast_log
Definition: astobj2.c:42
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_callback_data(container, flags, cb_fn, arg, data)
Definition: astobj2.h:1723
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_MULTIPLE
Definition: astobj2.h:1049
Bridging API.
void ast_bridge_set_transfer_variables(struct ast_channel *chan, const char *value, int is_attended)
Set the relevant transfer variables for a single channel.
Definition: bridge.c:4352
int ast_bridge_channel_write_park(struct ast_bridge_channel *bridge_channel, const char *parkee_uuid, const char *parker_uuid, const char *app_data)
Have a bridge channel park a channel in the bridge.
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
Definition: channel.c:10586
#define ast_channel_lock(chan)
Definition: channel.h:2968
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct ast_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel's bridge pointer.
Definition: channel.c:10604
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:3015
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1473
#define ast_channel_unlock(chan)
Definition: channel.h:2969
Standard Command Line Interface.
Configuration option-handling.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
Call Parking and Pickup API Includes code and algorithms from the Zapata library.
int ast_bridge_add_channel(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_bridge_features *features, int play_tone, const char *xfersound)
Add an arbitrary channel to a bridge.
Definition: bridge.c:2471
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:2011
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1969
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:2047
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2001
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1630
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:2055
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:1890
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7511
struct stasis_topic * ast_parking_topic(void)
accessor for the parking stasis topic
Definition: parking.c:67
struct stasis_message_type * ast_parked_call_type(void)
accessor for the parked call stasis message type
struct ast_channel_snapshot * ast_channel_snapshot_create(struct ast_channel *chan)
Generate a snapshot of the channel state. This is an ao2 object, so ao2_cleanup() to deallocate.
Configuration File Parser.
#define LOG_ERROR
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:253
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:191
#define EVENT_FLAG_CALL
Definition: manager.h:76
struct ast_str * ast_manager_build_channel_state_string_prefix(const struct ast_channel_snapshot *snapshot, const char *prefix)
Generate the AMI message body from a channel snapshot.
Asterisk module definitions.
struct ast_parked_call_payload * ast_parked_call_payload_create(enum ast_parked_call_event_type event_type, struct ast_channel_snapshot *parkee_snapshot, const char *parker_dial_string, struct ast_channel_snapshot *retriever_snapshot, const char *parkinglot, unsigned int parkingspace, unsigned long int timeout, unsigned long int duration)
Constructor for parked_call_payload objects.
Definition: parking.c:82
ast_parked_call_event_type
Defines the type of parked call message being published.
Definition: parking.h:46
@ PARKED_CALL
Definition: parking.h:47
@ PARKED_CALL_TIMEOUT
Definition: parking.h:48
@ PARKED_CALL_UNPARKED
Definition: parking.h:50
@ PARKED_CALL_FAILED
Definition: parking.h:51
@ PARKED_CALL_GIVEUP
Definition: parking.h:49
@ PARKED_CALL_SWAP
Definition: parking.h:52
struct ast_bridge * park_common_setup(struct ast_channel *parkee, struct ast_channel *parker, const char *lot_name, const char *comeback_override, int use_ringing, int randomize, int time_limit, int silence_announcements)
Setup a parked call on a parking bridge without needing to parse appdata.
int create_parked_subscription(struct ast_channel *chan, const char *parkee_uuid, int hangup_after)
Create a parking announcement subscription.
static void manager_park_bridged(struct mansession *s, const struct message *m, struct ast_channel *chan, struct ast_channel *parker_chan, const char *parkinglot, int timeout_override)
int load_parking_manager(void)
Register manager actions and setup subscriptions for stasis events.
void unload_parking_manager(void)
Unregister manager actions and remove subscriptions for stasis events.
static struct stasis_subscription * parking_sub
subscription to the parking lot topic
static void manager_park_unbridged(struct mansession *s, const struct message *m, struct ast_channel *chan, const char *parkinglot, int timeout_override)
static int manager_park(struct mansession *s, const struct message *m)
static struct ast_parked_call_payload * parked_call_payload_from_failure(struct ast_channel *chan)
void publish_parked_call(struct parked_user *pu, enum ast_parked_call_event_type event_type)
Publish a stasis parked call message for a given parked user.
static void parking_manager_disable_stasis(void)
static void manager_parking_status_single_lot(struct mansession *s, const struct message *m, const char *id_text, const char *lot_name)
static struct ast_str * manager_build_parked_call_string(const struct ast_parked_call_payload *payload)
Builds a manager string based on the contents of a parked call payload.
static void manager_parking_status_all_lots(struct mansession *s, const struct message *m, const char *id_text)
static void parked_call_message_response(struct ast_parked_call_payload *parked_call)
static void parking_manager_enable_stasis(void)
static int manager_parking_status(struct mansession *s, const struct message *m)
static void parking_event_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
void publish_parked_call_failure(struct ast_channel *parkee)
Publish a stasis parked call message for the channel indicating failure to park.
static int manager_append_event_parking_lot_data_cb(void *obj, void *arg, void *data, int flags)
static struct ast_parked_call_payload * parked_call_payload_from_parked_user(struct parked_user *pu, enum ast_parked_call_event_type event_type)
static int manager_parking_lot_list(struct mansession *s, const struct message *m)
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
static int total
Definition: res_adsi.c:970
struct stasis_forward * sub
Definition: res_corosync.c:240
Call Parking Resource Internal API.
struct ao2_container * get_parking_lot_container(void)
Get a pointer to the parking lot container for purposes such as iteration.
Definition: res_parking.c:597
struct parking_lot * parking_lot_find_by_name(const char *lot_name)
Find a parking lot based on its name.
Definition: res_parking.c:602
#define NULL
Definition: resample.c:96
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
@ STASIS_SUBSCRIPTION_FILTER_SELECTIVE
Definition: stasis.h:297
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition: stasis.c:1024
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition: stasis.c:1078
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition: stasis.c:1135
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1512
#define stasis_subscribe(topic, callback, data)
Definition: stasis.h:649
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Structure that contains information regarding a channel in a bridge.
struct ast_channel * chan
Structure that contains information about a bridge.
Definition: bridge.h:349
Structure representing a snapshot of channel state.
Main Channel structure associated with a channel.
const ast_string_field parkinglot
const char * data
A parked call message payload.
Definition: parking.h:59
unsigned int parkingspace
Definition: parking.h:65
long unsigned int duration
Definition: parking.h:64
const ast_string_field parkinglot
Definition: parking.h:69
struct ast_channel_snapshot * retriever
Definition: parking.h:61
long unsigned int timeout
Definition: parking.h:63
struct ast_channel_snapshot * parkee
Definition: parking.h:60
enum ast_parked_call_event_type event_type
Definition: parking.h:62
const ast_string_field parker_dial_string
Definition: parking.h:69
Support for dynamic strings.
Definition: strings.h:623
In case you didn't read that giant block of text above the mansession_session struct,...
Definition: manager.c:326
const char * id_text
char * parker_dial_string
Definition: res_parking.h:111
unsigned int time_limit
Definition: res_parking.h:112
int parking_space
Definition: res_parking.h:109
struct ast_channel * chan
Definition: res_parking.h:106
struct parking_lot * lot
Definition: res_parking.h:113
struct ast_channel_snapshot * retriever
Definition: res_parking.h:107
struct timeval start
Definition: res_parking.h:108
unsigned int parkingtime
Definition: res_parking.h:69
struct parking_lot_cfg * cfg
Definition: res_parking.h:96
const ast_string_field name
Definition: res_parking.h:102
struct ao2_container * parked_users
Definition: res_parking.h:95
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
FILE * out
Definition: utils/frame.c:33
Utility functions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define MAX(a, b)
Definition: utils.h:233