Asterisk - The Open Source Telephony Project GIT-master-754dea3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 <since>
43 <version>11.0.0</version>
44 </since>
45 <synopsis>
46 Get a list of parking lots
47 </synopsis>
48 <syntax>
49 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
50 </syntax>
51 <description>
52 <para>List all parking lots as a series of AMI events</para>
53 </description>
54 </manager>
55 <manager name="ParkedCalls" language="en_US">
56 <since>
57 <version>0.7.2</version>
58 </since>
59 <synopsis>
60 List parked calls.
61 </synopsis>
62 <syntax>
63 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
64 <parameter name="ParkingLot">
65 <para>If specified, only show parked calls from the parking lot with this name.</para>
66 </parameter>
67 </syntax>
68 <description>
69 <para>List parked calls.</para>
70 </description>
71 </manager>
72 <manager name="Park" language="en_US">
73 <since>
74 <version>1.4.0</version>
75 </since>
76 <synopsis>
77 Park a channel.
78 </synopsis>
79 <syntax>
80 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
81 <parameter name="Channel" required="true">
82 <para>Channel name to park.</para>
83 </parameter>
84 <parameter name="TimeoutChannel" required="false">
85 <para>Channel name to use when constructing the dial string that will be dialed if the parked channel
86 times out. If <literal>TimeoutChannel</literal> is in a two party bridge with
87 <literal>Channel</literal>, then <literal>TimeoutChannel</literal> will receive an announcement and be
88 treated as having parked <literal>Channel</literal> in the same manner as the Park Call DTMF feature.
89 </para>
90 </parameter>
91 <parameter name="AnnounceChannel" required="false">
92 <para>If specified, then this channel will receive an announcement when <literal>Channel</literal>
93 is parked if <literal>AnnounceChannel</literal> is in a state where it can receive announcements
94 (AnnounceChannel must be bridged). <literal>AnnounceChannel</literal> has no bearing on the actual
95 state of the parked call.</para>
96 </parameter>
97 <parameter name="Timeout" required="false">
98 <para>Overrides the timeout of the parking lot for this park action. Specified in milliseconds, but will be converted to
99 seconds. Use a value of 0 to disable the timeout.
100 </para>
101 </parameter>
102 <parameter name="Parkinglot" required="false">
103 <para>The parking lot to use when parking the channel</para>
104 </parameter>
105 <parameter name="ParkingSpace" required="false">
106 <para>The parking space extension in the parking lot.
107 If the space is already in use then execution will continue at the next priority.
108 </para>
109 </parameter>
110 </syntax>
111 <description>
112 <para>Park an arbitrary channel with optional arguments for specifying the parking lot used, how long
113 the channel should remain parked, and what dial string to use as the parker if the call times out.
114 </para>
115 </description>
116 </manager>
117 <managerEvent language="en_US" name="ParkedCall">
118 <managerEventInstance class="EVENT_FLAG_CALL">
119 <since>
120 <version>12.0.0</version>
121 </since>
122 <synopsis>Raised when a channel is parked.</synopsis>
123 <syntax>
124 <channel_snapshot prefix="Parkee"/>
125 <parameter name="ParkerDialString">
126 <para>Dial String that can be used to call back the parker on ParkingTimeout.</para>
127 </parameter>
128 <parameter name="Parkinglot">
129 <para>Name of the parking lot that the parkee is parked in</para>
130 </parameter>
131 <parameter name="ParkingSpace">
132 <para>Parking Space that the parkee is parked in</para>
133 </parameter>
134 <parameter name="ParkingTimeout">
135 <para>Time remaining until the parkee is forcefully removed from parking in seconds</para>
136 </parameter>
137 <parameter name="ParkingDuration">
138 <para>Time the parkee has been in the parking bridge (in seconds)</para>
139 </parameter>
140 </syntax>
141 </managerEventInstance>
142 </managerEvent>
143 <managerEvent language="en_US" name="ParkedCallTimeOut">
144 <managerEventInstance class="EVENT_FLAG_CALL">
145 <since>
146 <version>12.0.0</version>
147 </since>
148 <synopsis>Raised when a channel leaves a parking lot due to reaching the time limit of being parked.</synopsis>
149 <syntax>
150 <channel_snapshot prefix="Parkee"/>
151 <channel_snapshot prefix="Parker"/>
152 <xi:include xpointer="xpointer(/docs/managerEvent[@name='ParkedCall']/managerEventInstance/syntax/parameter)" />
153 </syntax>
154 </managerEventInstance>
155 </managerEvent>
156 <managerEvent language="en_US" name="ParkedCallGiveUp">
157 <managerEventInstance class="EVENT_FLAG_CALL">
158 <since>
159 <version>12.0.0</version>
160 </since>
161 <synopsis>Raised when a channel leaves a parking lot because it hung up without being answered.</synopsis>
162 <syntax>
163 <channel_snapshot prefix="Parkee"/>
164 <channel_snapshot prefix="Parker"/>
165 <xi:include xpointer="xpointer(/docs/managerEvent[@name='ParkedCall']/managerEventInstance/syntax/parameter)" />
166 </syntax>
167 </managerEventInstance>
168 </managerEvent>
169 <managerEvent language="en_US" name="UnParkedCall">
170 <managerEventInstance class="EVENT_FLAG_CALL">
171 <since>
172 <version>12.0.0</version>
173 </since>
174 <synopsis>Raised when a channel leaves a parking lot because it was retrieved from the parking lot and reconnected.</synopsis>
175 <syntax>
176 <channel_snapshot prefix="Parkee"/>
177 <channel_snapshot prefix="Parker"/>
178 <xi:include xpointer="xpointer(/docs/managerEvent[@name='ParkedCall']/managerEventInstance/syntax/parameter)" />
179 <channel_snapshot prefix="Retriever"/>
180 </syntax>
181 </managerEventInstance>
182 </managerEvent>
183 <managerEvent language="en_US" name="ParkedCallSwap">
184 <managerEventInstance class="EVENT_FLAG_CALL">
185 <since>
186 <version>13.5.0</version>
187 </since>
188 <synopsis>Raised when a channel takes the place of a previously parked channel</synopsis>
189 <syntax>
190 <channel_snapshot prefix="Parkee"/>
191 <channel_snapshot prefix="Parker"/>
192 <xi:include xpointer="xpointer(/docs/managerEvent[@name='ParkedCall']/managerEventInstance/syntax/parameter)" />
193 </syntax>
194 <description>
195 <para>This event is raised when a channel initially parked in the parking lot
196 is swapped out with a different channel. The most common case for this is when
197 an attended transfer to a parking lot occurs. The Parkee information in the event
198 will indicate the party that was swapped into the parking lot.</para>
199 </description>
200 </managerEventInstance>
201 </managerEvent>
202 ***/
203
204/*! \brief subscription to the parking lot topic */
206
208{
209 RAII_VAR(struct ast_channel_snapshot *, parkee_snapshot, NULL, ao2_cleanup);
210
211 ast_channel_lock(chan);
212 parkee_snapshot = ast_channel_snapshot_create(chan);
213 ast_channel_unlock(chan);
214 if (!parkee_snapshot) {
215 return NULL;
216 }
217
218 return ast_parked_call_payload_create(PARKED_CALL_FAILED, parkee_snapshot, NULL, NULL, NULL, 0, 0, 0);
219}
220
222{
223 RAII_VAR(struct ast_channel_snapshot *, parkee_snapshot, NULL, ao2_cleanup);
224 long int timeout;
225 long int duration;
226 struct timeval now = ast_tvnow();
227 const char *lot_name = pu->lot->name;
228
230 parkee_snapshot = ast_channel_snapshot_create(pu->chan);
232 if (!parkee_snapshot) {
233 return NULL;
234 }
235
236 timeout = pu->start.tv_sec + (long) pu->time_limit - now.tv_sec;
237 duration = now.tv_sec - pu->start.tv_sec;
238
239 return ast_parked_call_payload_create(event_type, parkee_snapshot, pu->parker_dial_string, pu->retriever, lot_name, pu->parking_space, timeout, duration);
240
241}
242
243/*! \brief Builds a manager string based on the contents of a parked call payload */
245{
246 struct ast_str *out = ast_str_create(1024);
247 RAII_VAR(struct ast_str *, parkee_string, NULL, ast_free);
248 RAII_VAR(struct ast_str *, retriever_string, NULL, ast_free);
249
250 if (!out) {
251 return NULL;
252 }
253
254 parkee_string = ast_manager_build_channel_state_string_prefix(payload->parkee, "Parkee");
255 if (!parkee_string) {
256 ast_free(out);
257 return NULL;
258 }
259
260 if (payload->retriever) {
261 retriever_string = ast_manager_build_channel_state_string_prefix(payload->retriever, "Retriever");
262 if (!retriever_string) {
263 ast_free(out);
264 return NULL;
265 }
266 }
267
268 ast_str_set(&out, 0,
269 "%s" /* parkee channel state */
270 "%s" /* retriever channel state (when available) */
271 "ParkerDialString: %s\r\n"
272 "Parkinglot: %s\r\n"
273 "ParkingSpace: %u\r\n"
274 "ParkingTimeout: %lu\r\n"
275 "ParkingDuration: %lu\r\n",
276
277 ast_str_buffer(parkee_string),
278 retriever_string ? ast_str_buffer(retriever_string) : "",
279 payload->parker_dial_string,
280 payload->parkinglot,
281 payload->parkingspace,
282 payload->timeout,
283 payload->duration);
284
285 return out;
286}
287
288static void manager_parking_status_single_lot(struct mansession *s, const struct message *m, const char *id_text, const char *lot_name)
289{
290 RAII_VAR(struct parking_lot *, curlot, NULL, ao2_cleanup);
291 struct parked_user *curuser;
292 struct ao2_iterator iter_users;
293 int total = 0;
294
295 curlot = parking_lot_find_by_name(lot_name);
296 if (!curlot) {
297 astman_send_error(s, m, "Requested parking lot could not be found.");
298 return;
299 }
300
301 astman_send_listack(s, m, "Parked calls will follow", "start");
302
303 iter_users = ao2_iterator_init(curlot->parked_users, 0);
304 while ((curuser = ao2_iterator_next(&iter_users))) {
306 RAII_VAR(struct ast_str *, parked_call_string, NULL, ast_free);
307
309 if (!payload) {
310 ao2_ref(curuser, -1);
311 break;
312 }
313
314 parked_call_string = manager_build_parked_call_string(payload);
315 if (!parked_call_string) {
316 ao2_ref(curuser, -1);
317 break;
318 }
319
320 total++;
321
322 astman_append(s, "Event: ParkedCall\r\n"
323 "%s" /* The parked call string */
324 "%s" /* The action ID */
325 "\r\n",
326 ast_str_buffer(parked_call_string),
327 id_text);
328
329 ao2_ref(curuser, -1);
330 }
331 ao2_iterator_destroy(&iter_users);
332
333 astman_send_list_complete_start(s, m, "ParkedCallsComplete", total);
334 astman_append(s, "Total: %d\r\n", total);
336}
337
338static void manager_parking_status_all_lots(struct mansession *s, const struct message *m, const char *id_text)
339{
340 struct parked_user *curuser;
341 struct ao2_container *lot_container;
342 struct ao2_iterator iter_lots;
343 struct ao2_iterator iter_users;
344 struct parking_lot *curlot;
345 int total = 0;
346
347 lot_container = get_parking_lot_container();
348 if (!lot_container) {
349 ast_log(LOG_ERROR, "Failed to obtain parking lot list. Action canceled.\n");
350 astman_send_error(s, m, "Could not create parking lot list");
351 return;
352 }
353
354 astman_send_listack(s, m, "Parked calls will follow", "start");
355
356 iter_lots = ao2_iterator_init(lot_container, 0);
357 while ((curlot = ao2_iterator_next(&iter_lots))) {
358 iter_users = ao2_iterator_init(curlot->parked_users, 0);
359 while ((curuser = ao2_iterator_next(&iter_users))) {
361 RAII_VAR(struct ast_str *, parked_call_string, NULL, ast_free);
362
364 if (!payload) {
365 ao2_ref(curuser, -1);
366 ao2_iterator_destroy(&iter_users);
367 ao2_ref(curlot, -1);
368 goto abort_list;
369 }
370
371 parked_call_string = manager_build_parked_call_string(payload);
372 if (!parked_call_string) {
373 ao2_ref(curuser, -1);
374 ao2_iterator_destroy(&iter_users);
375 ao2_ref(curlot, -1);
376 goto abort_list;
377 }
378
379 total++;
380
381 astman_append(s, "Event: ParkedCall\r\n"
382 "%s" /* The parked call string */
383 "%s" /* The action ID */
384 "\r\n",
385 ast_str_buffer(parked_call_string),
386 id_text);
387
388 ao2_ref(curuser, -1);
389 }
390 ao2_iterator_destroy(&iter_users);
391 ao2_ref(curlot, -1);
392 }
393abort_list:
394 ao2_iterator_destroy(&iter_lots);
395
396 astman_send_list_complete_start(s, m, "ParkedCallsComplete", total);
397 astman_append(s, "Total: %d\r\n", total);
399}
400
401static int manager_parking_status(struct mansession *s, const struct message *m)
402{
403 const char *id = astman_get_header(m, "ActionID");
404 const char *lot_name = astman_get_header(m, "ParkingLot");
405 char id_text[256];
406
407 id_text[0] = '\0';
408 if (!ast_strlen_zero(id)) {
409 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
410 }
411
412 if (!ast_strlen_zero(lot_name)) {
413 manager_parking_status_single_lot(s, m, id_text, lot_name);
414 } else {
415 manager_parking_status_all_lots(s, m, id_text);
416 }
417
418 return 0;
419}
420
422 const char *id_text;
423 int count;
424};
425
426static int manager_append_event_parking_lot_data_cb(void *obj, void *arg, void *data, int flags)
427{
428 struct parking_lot *curlot = obj;
429 struct mansession *s = arg;
430 struct park_list_data *list_data = data;
431
432 astman_append(s, "Event: Parkinglot\r\n"
433 "%s" /* The Action ID */
434 "Name: %s\r\n"
435 "StartSpace: %d\r\n"
436 "StopSpace: %d\r\n"
437 "Timeout: %u\r\n"
438 "\r\n",
439 list_data->id_text,
440 curlot->name,
441 curlot->cfg->parking_start,
442 curlot->cfg->parking_stop,
443 curlot->cfg->parkingtime);
444 ++list_data->count;
445
446 return 0;
447}
448
449static int manager_parking_lot_list(struct mansession *s, const struct message *m)
450{
451 const char *id = astman_get_header(m, "ActionID");
452 struct ao2_container *lot_container;
453 char id_text[256];
454 struct park_list_data list_data;
455
456 id_text[0] = '\0';
457 if (!ast_strlen_zero(id)) {
458 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
459 }
460
461 lot_container = get_parking_lot_container();
462 if (!lot_container) {
463 ast_log(LOG_ERROR, "Failed to obtain parking lot list. Action canceled.\n");
464 astman_send_error(s, m, "Could not create parking lot list");
465 return 0;
466 }
467
468 astman_send_listack(s, m, "Parking lots will follow", "start");
469
470 list_data.id_text = id_text;
471 list_data.count = 0;
474
475 astman_send_list_complete_start(s, m, "ParkinglotsComplete", list_data.count);
477
478 return 0;
479}
480
481static void manager_park_unbridged(struct mansession *s, const struct message *m,
482 struct ast_channel *chan, const char *parkinglot, int timeout_override)
483{
484 struct ast_bridge *parking_bridge = park_common_setup(chan,
485 chan, parkinglot, NULL, 0, 0, timeout_override, 1);
486
487 if (!parking_bridge) {
488 astman_send_error(s, m, "Park action failed\n");
489 return;
490 }
491
492 if (ast_bridge_add_channel(parking_bridge, chan, NULL, 0, NULL)) {
493 astman_send_error(s, m, "Park action failed\n");
494 ao2_cleanup(parking_bridge);
495 return;
496 }
497
498 astman_send_ack(s, m, "Park successful\n");
499 ao2_cleanup(parking_bridge);
500}
501
502static void manager_park_bridged(struct mansession *s, const struct message *m,
503 struct ast_channel *chan, struct ast_channel *parker_chan,
504 const char *parkinglot, int timeout_override)
505{
506 struct ast_bridge_channel *bridge_channel;
507 char *app_data;
508
509 if (timeout_override != -1) {
510 if (ast_asprintf(&app_data, "%s,t(%d)", parkinglot, timeout_override) == -1) {
511 astman_send_error(s, m, "Park action failed\n");
512 return;
513 }
514 } else {
515 if (ast_asprintf(&app_data, "%s", parkinglot) == -1) {
516 astman_send_error(s, m, "Park action failed\n");
517 return;
518 }
519 }
520
521 ast_channel_lock(parker_chan);
522 bridge_channel = ast_channel_get_bridge_channel(parker_chan);
523 ast_channel_unlock(parker_chan);
524
525 if (!bridge_channel) {
527 astman_send_error(s, m, "Park action failed\n");
528 return;
529 }
530
531 /* Subscribe to park messages for the channel being parked */
534 astman_send_error(s, m, "Park action failed\n");
535 ao2_cleanup(bridge_channel);
536 return;
537 }
538
540 ast_channel_uniqueid(parker_chan), app_data);
541
543
544 astman_send_ack(s, m, "Park successful\n");
545 ao2_cleanup(bridge_channel);
546}
547
548static int manager_park(struct mansession *s, const struct message *m)
549{
550 const char *channel = astman_get_header(m, "Channel");
551 const char *timeout_channel = S_OR(astman_get_header(m, "TimeoutChannel"), astman_get_header(m, "Channel2"));
552 const char *announce_channel = astman_get_header(m, "AnnounceChannel");
553 const char *timeout = astman_get_header(m, "Timeout");
554 const char *parkinglot = astman_get_header(m, "Parkinglot");
555 const char *parkingspace = astman_get_header(m, "ParkingSpace");
556 char buf[BUFSIZ];
557 int timeout_override = -1;
558
559 RAII_VAR(struct ast_channel *, parker_chan, NULL, ao2_cleanup);
561
562 if (ast_strlen_zero(channel)) {
563 astman_send_error(s, m, "Channel not specified");
564 return 0;
565 }
566
567 if (!ast_strlen_zero(timeout)) {
568 if (sscanf(timeout, "%30d", &timeout_override) != 1 || timeout_override < 0) {
569 astman_send_error(s, m, "Invalid Timeout value.");
570 return 0;
571 }
572
573 if (timeout_override) {
574 /* If greater than zero, convert to seconds for internal use. Must be >= 1 second. */
575 timeout_override = MAX(1, timeout_override / 1000);
576 }
577 }
578
579 if (!(chan = ast_channel_get_by_name(channel))) {
580 snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
581 astman_send_error(s, m, buf);
582 return 0;
583 }
584
585 if (!ast_strlen_zero(timeout_channel)) {
587 ast_bridge_set_transfer_variables(chan, timeout_channel, 0);
589 }
590
591 if (!ast_strlen_zero(parkingspace)) {
592 pbx_builtin_setvar_helper(chan, "PARKINGEXTEN", parkingspace);
593 }
594
595 parker_chan = ast_channel_bridge_peer(chan);
596 if (!parker_chan || strcmp(ast_channel_name(parker_chan), timeout_channel)) {
597 if (!ast_strlen_zero(announce_channel)) {
598 struct ast_channel *announce_chan = ast_channel_get_by_name(announce_channel);
599 if (!announce_channel) {
600 astman_send_error(s, m, "AnnounceChannel does not exist");
601 return 0;
602 }
603
604 create_parked_subscription(announce_chan, ast_channel_uniqueid(chan), 0);
605 ast_channel_cleanup(announce_chan);
606 }
607
608 manager_park_unbridged(s, m, chan, parkinglot, timeout_override);
609 return 0;
610 }
611
612 if (!ast_strlen_zero(announce_channel) && strcmp(announce_channel, timeout_channel)) {
613 /* When using an announce_channel in bridge mode, only add the announce channel if it isn't
614 * the same as the timeout channel (which will play announcements anyway) */
615 struct ast_channel *announce_chan = ast_channel_get_by_name(announce_channel);
616 if (!announce_channel) {
617 astman_send_error(s, m, "AnnounceChannel does not exist");
618 return 0;
619 }
620
621 create_parked_subscription(announce_chan, ast_channel_uniqueid(chan), 0);
622 ast_channel_cleanup(announce_chan);
623 }
624
625 manager_park_bridged(s, m, chan, parker_chan, parkinglot, timeout_override);
626 return 0;
627}
628
630{
632 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
633
634 if (!ast_parked_call_type()) {
635 return;
636 }
637
638 payload = parked_call_payload_from_failure(parkee);
639 if (!payload) {
640 return;
641 }
642
644 if (!msg) {
645 return;
646 }
647
649}
650
652{
654 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
655
656 if (!ast_parked_call_type()) {
657 return;
658 }
659
660 payload = parked_call_payload_from_parked_user(pu, event_type);
661 if (!payload) {
662 return;
663 }
664
666 if (!msg) {
667 return;
668 }
669
671}
672
674{
675 char *event_type = "";
676 RAII_VAR(struct ast_str *, parked_call_string, NULL, ast_free);
677
678 switch (parked_call->event_type) {
679 case PARKED_CALL:
680 event_type = "ParkedCall";
681 break;
683 event_type = "ParkedCallTimeOut";
684 break;
686 event_type = "ParkedCallGiveUp";
687 break;
689 event_type = "UnParkedCall";
690 break;
691 case PARKED_CALL_SWAP:
692 event_type = "ParkedCallSwap";
693 break;
695 /* PARKED_CALL_FAILED doesn't currently get a message and is used exclusively for bridging */
696 return;
697 }
698
699 parked_call_string = manager_build_parked_call_string(parked_call);
700 if (!parked_call_string) {
701 ast_log(LOG_ERROR, "Failed to issue an AMI event of '%s' in response to a stasis message.\n", event_type);
702 return;
703 }
704
705 manager_event(EVENT_FLAG_CALL, event_type,
706 "%s",
707 ast_str_buffer(parked_call_string)
708 );
709}
710
712{
714 struct ast_parked_call_payload *parked_call_message = stasis_message_data(message);
715 parked_call_message_response(parked_call_message);
716 }
717}
718
720{
721 if (!parking_sub) {
725 }
726}
727
729{
730 int res;
731
736 return res ? -1 : 0;
737}
738
740{
742}
743
745{
746 ast_manager_unregister("Parkinglots");
747 ast_manager_unregister("ParkedCalls");
750}
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:4421
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:10590
#define ast_channel_lock(chan)
Definition: channel.h:2970
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:10608
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:3017
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1481
#define ast_channel_unlock(chan)
Definition: channel.h:2971
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:2540
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:2028
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1986
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:2064
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2018
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1647
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:2072
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:1907
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7697
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:254
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:192
#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:657
struct parking_lot * parking_lot_find_by_name(const char *lot_name)
Find a parking lot based on its name.
Definition: res_parking.c:662
#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:1050
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:1104
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:1161
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:1538
#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:353
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:327
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