Asterisk - The Open Source Telephony Project  18.5.0
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 <[email protected]>
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 <[email protected]>
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  </syntax>
97  <description>
98  <para>Park an arbitrary channel with optional arguments for specifying the parking lot used, how long
99  the channel should remain parked, and what dial string to use as the parker if the call times out.
100  </para>
101  </description>
102  </manager>
103  <managerEvent language="en_US" name="ParkedCall">
104  <managerEventInstance class="EVENT_FLAG_CALL">
105  <synopsis>Raised when a channel is parked.</synopsis>
106  <syntax>
107  <channel_snapshot prefix="Parkee"/>
108  <parameter name="ParkerDialString">
109  <para>Dial String that can be used to call back the parker on ParkingTimeout.</para>
110  </parameter>
111  <parameter name="Parkinglot">
112  <para>Name of the parking lot that the parkee is parked in</para>
113  </parameter>
114  <parameter name="ParkingSpace">
115  <para>Parking Space that the parkee is parked in</para>
116  </parameter>
117  <parameter name="ParkingTimeout">
118  <para>Time remaining until the parkee is forcefully removed from parking in seconds</para>
119  </parameter>
120  <parameter name="ParkingDuration">
121  <para>Time the parkee has been in the parking bridge (in seconds)</para>
122  </parameter>
123  </syntax>
124  </managerEventInstance>
125  </managerEvent>
126  <managerEvent language="en_US" name="ParkedCallTimeOut">
127  <managerEventInstance class="EVENT_FLAG_CALL">
128  <synopsis>Raised when a channel leaves a parking lot due to reaching the time limit of being parked.</synopsis>
129  <syntax>
130  <channel_snapshot prefix="Parkee"/>
131  <channel_snapshot prefix="Parker"/>
132  <xi:include xpointer="xpointer(/docs/managerEvent[@name='ParkedCall']/managerEventInstance/syntax/parameter)" />
133  </syntax>
134  </managerEventInstance>
135  </managerEvent>
136  <managerEvent language="en_US" name="ParkedCallGiveUp">
137  <managerEventInstance class="EVENT_FLAG_CALL">
138  <synopsis>Raised when a channel leaves a parking lot because it hung up without being answered.</synopsis>
139  <syntax>
140  <channel_snapshot prefix="Parkee"/>
141  <channel_snapshot prefix="Parker"/>
142  <xi:include xpointer="xpointer(/docs/managerEvent[@name='ParkedCall']/managerEventInstance/syntax/parameter)" />
143  </syntax>
144  </managerEventInstance>
145  </managerEvent>
146  <managerEvent language="en_US" name="UnParkedCall">
147  <managerEventInstance class="EVENT_FLAG_CALL">
148  <synopsis>Raised when a channel leaves a parking lot because it was retrieved from the parking lot and reconnected.</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  <channel_snapshot prefix="Retriever"/>
154  </syntax>
155  </managerEventInstance>
156  </managerEvent>
157  <managerEvent language="en_US" name="ParkedCallSwap">
158  <managerEventInstance class="EVENT_FLAG_CALL">
159  <synopsis>Raised when a channel takes the place of a previously parked channel</synopsis>
160  <syntax>
161  <channel_snapshot prefix="Parkee"/>
162  <channel_snapshot prefix="Parker"/>
163  <xi:include xpointer="xpointer(/docs/managerEvent[@name='ParkedCall']/managerEventInstance/syntax/parameter)" />
164  </syntax>
165  <description>
166  <para>This event is raised when a channel initially parked in the parking lot
167  is swapped out with a different channel. The most common case for this is when
168  an attended transfer to a parking lot occurs. The Parkee information in the event
169  will indicate the party that was swapped into the parking lot.</para>
170  </description>
171  </managerEventInstance>
172  </managerEvent>
173  ***/
174 
175 /*! \brief subscription to the parking lot topic */
177 
179 {
180  RAII_VAR(struct ast_channel_snapshot *, parkee_snapshot, NULL, ao2_cleanup);
181 
182  ast_channel_lock(chan);
183  parkee_snapshot = ast_channel_snapshot_create(chan);
184  ast_channel_unlock(chan);
185  if (!parkee_snapshot) {
186  return NULL;
187  }
188 
189  return ast_parked_call_payload_create(PARKED_CALL_FAILED, parkee_snapshot, NULL, NULL, NULL, 0, 0, 0);
190 }
191 
193 {
194  RAII_VAR(struct ast_channel_snapshot *, parkee_snapshot, NULL, ao2_cleanup);
195  long int timeout;
196  long int duration;
197  struct timeval now = ast_tvnow();
198  const char *lot_name = pu->lot->name;
199 
200  ast_channel_lock(pu->chan);
201  parkee_snapshot = ast_channel_snapshot_create(pu->chan);
203  if (!parkee_snapshot) {
204  return NULL;
205  }
206 
207  timeout = pu->start.tv_sec + (long) pu->time_limit - now.tv_sec;
208  duration = now.tv_sec - pu->start.tv_sec;
209 
210  return ast_parked_call_payload_create(event_type, parkee_snapshot, pu->parker_dial_string, pu->retriever, lot_name, pu->parking_space, timeout, duration);
211 
212 }
213 
214 /*! \brief Builds a manager string based on the contents of a parked call payload */
216 {
217  struct ast_str *out = ast_str_create(1024);
218  RAII_VAR(struct ast_str *, parkee_string, NULL, ast_free);
219  RAII_VAR(struct ast_str *, retriever_string, NULL, ast_free);
220 
221  if (!out) {
222  return NULL;
223  }
224 
225  parkee_string = ast_manager_build_channel_state_string_prefix(payload->parkee, "Parkee");
226  if (!parkee_string) {
227  ast_free(out);
228  return NULL;
229  }
230 
231  if (payload->retriever) {
232  retriever_string = ast_manager_build_channel_state_string_prefix(payload->retriever, "Retriever");
233  if (!retriever_string) {
234  ast_free(out);
235  return NULL;
236  }
237  }
238 
239  ast_str_set(&out, 0,
240  "%s" /* parkee channel state */
241  "%s" /* retriever channel state (when available) */
242  "ParkerDialString: %s\r\n"
243  "Parkinglot: %s\r\n"
244  "ParkingSpace: %u\r\n"
245  "ParkingTimeout: %lu\r\n"
246  "ParkingDuration: %lu\r\n",
247 
248  ast_str_buffer(parkee_string),
249  retriever_string ? ast_str_buffer(retriever_string) : "",
250  payload->parker_dial_string,
251  payload->parkinglot,
252  payload->parkingspace,
253  payload->timeout,
254  payload->duration);
255 
256  return out;
257 }
258 
259 static void manager_parking_status_single_lot(struct mansession *s, const struct message *m, const char *id_text, const char *lot_name)
260 {
261  RAII_VAR(struct parking_lot *, curlot, NULL, ao2_cleanup);
262  struct parked_user *curuser;
263  struct ao2_iterator iter_users;
264  int total = 0;
265 
266  curlot = parking_lot_find_by_name(lot_name);
267  if (!curlot) {
268  astman_send_error(s, m, "Requested parking lot could not be found.");
269  return;
270  }
271 
272  astman_send_listack(s, m, "Parked calls will follow", "start");
273 
274  iter_users = ao2_iterator_init(curlot->parked_users, 0);
275  while ((curuser = ao2_iterator_next(&iter_users))) {
276  RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup);
277  RAII_VAR(struct ast_str *, parked_call_string, NULL, ast_free);
278 
280  if (!payload) {
281  ao2_ref(curuser, -1);
282  break;
283  }
284 
285  parked_call_string = manager_build_parked_call_string(payload);
286  if (!parked_call_string) {
287  ao2_ref(curuser, -1);
288  break;
289  }
290 
291  total++;
292 
293  astman_append(s, "Event: ParkedCall\r\n"
294  "%s" /* The parked call string */
295  "%s" /* The action ID */
296  "\r\n",
297  ast_str_buffer(parked_call_string),
298  id_text);
299 
300  ao2_ref(curuser, -1);
301  }
302  ao2_iterator_destroy(&iter_users);
303 
304  astman_send_list_complete_start(s, m, "ParkedCallsComplete", total);
305  astman_append(s, "Total: %d\r\n", total);
307 }
308 
309 static void manager_parking_status_all_lots(struct mansession *s, const struct message *m, const char *id_text)
310 {
311  struct parked_user *curuser;
312  struct ao2_container *lot_container;
313  struct ao2_iterator iter_lots;
314  struct ao2_iterator iter_users;
315  struct parking_lot *curlot;
316  int total = 0;
317 
318  lot_container = get_parking_lot_container();
319  if (!lot_container) {
320  ast_log(LOG_ERROR, "Failed to obtain parking lot list. Action canceled.\n");
321  astman_send_error(s, m, "Could not create parking lot list");
322  return;
323  }
324 
325  astman_send_listack(s, m, "Parked calls will follow", "start");
326 
327  iter_lots = ao2_iterator_init(lot_container, 0);
328  while ((curlot = ao2_iterator_next(&iter_lots))) {
329  iter_users = ao2_iterator_init(curlot->parked_users, 0);
330  while ((curuser = ao2_iterator_next(&iter_users))) {
331  RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup);
332  RAII_VAR(struct ast_str *, parked_call_string, NULL, ast_free);
333 
335  if (!payload) {
336  ao2_ref(curuser, -1);
337  ao2_iterator_destroy(&iter_users);
338  ao2_ref(curlot, -1);
339  goto abort_list;
340  }
341 
342  parked_call_string = manager_build_parked_call_string(payload);
343  if (!parked_call_string) {
344  ao2_ref(curuser, -1);
345  ao2_iterator_destroy(&iter_users);
346  ao2_ref(curlot, -1);
347  goto abort_list;
348  }
349 
350  total++;
351 
352  astman_append(s, "Event: ParkedCall\r\n"
353  "%s" /* The parked call string */
354  "%s" /* The action ID */
355  "\r\n",
356  ast_str_buffer(parked_call_string),
357  id_text);
358 
359  ao2_ref(curuser, -1);
360  }
361  ao2_iterator_destroy(&iter_users);
362  ao2_ref(curlot, -1);
363  }
364 abort_list:
365  ao2_iterator_destroy(&iter_lots);
366 
367  astman_send_list_complete_start(s, m, "ParkedCallsComplete", total);
368  astman_append(s, "Total: %d\r\n", total);
370 }
371 
372 static int manager_parking_status(struct mansession *s, const struct message *m)
373 {
374  const char *id = astman_get_header(m, "ActionID");
375  const char *lot_name = astman_get_header(m, "ParkingLot");
376  char id_text[256];
377 
378  id_text[0] = '\0';
379  if (!ast_strlen_zero(id)) {
380  snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
381  }
382 
383  if (!ast_strlen_zero(lot_name)) {
384  manager_parking_status_single_lot(s, m, id_text, lot_name);
385  } else {
386  manager_parking_status_all_lots(s, m, id_text);
387  }
388 
389  return 0;
390 }
391 
393  const char *id_text;
394  int count;
395 };
396 
397 static int manager_append_event_parking_lot_data_cb(void *obj, void *arg, void *data, int flags)
398 {
399  struct parking_lot *curlot = obj;
400  struct mansession *s = arg;
401  struct park_list_data *list_data = data;
402 
403  astman_append(s, "Event: Parkinglot\r\n"
404  "%s" /* The Action ID */
405  "Name: %s\r\n"
406  "StartSpace: %d\r\n"
407  "StopSpace: %d\r\n"
408  "Timeout: %u\r\n"
409  "\r\n",
410  list_data->id_text,
411  curlot->name,
412  curlot->cfg->parking_start,
413  curlot->cfg->parking_stop,
414  curlot->cfg->parkingtime);
415  ++list_data->count;
416 
417  return 0;
418 }
419 
420 static int manager_parking_lot_list(struct mansession *s, const struct message *m)
421 {
422  const char *id = astman_get_header(m, "ActionID");
423  struct ao2_container *lot_container;
424  char id_text[256];
425  struct park_list_data list_data;
426 
427  id_text[0] = '\0';
428  if (!ast_strlen_zero(id)) {
429  snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
430  }
431 
432  lot_container = get_parking_lot_container();
433  if (!lot_container) {
434  ast_log(LOG_ERROR, "Failed to obtain parking lot list. Action canceled.\n");
435  astman_send_error(s, m, "Could not create parking lot list");
436  return 0;
437  }
438 
439  astman_send_listack(s, m, "Parking lots will follow", "start");
440 
441  list_data.id_text = id_text;
442  list_data.count = 0;
443  ao2_callback_data(lot_container, OBJ_MULTIPLE | OBJ_NODATA,
445 
446  astman_send_list_complete_start(s, m, "ParkinglotsComplete", list_data.count);
448 
449  return 0;
450 }
451 
452 static void manager_park_unbridged(struct mansession *s, const struct message *m,
453  struct ast_channel *chan, const char *parkinglot, int timeout_override)
454 {
455  struct ast_bridge *parking_bridge = park_common_setup(chan,
456  chan, parkinglot, NULL, 0, 0, timeout_override, 1);
457 
458  if (!parking_bridge) {
459  astman_send_error(s, m, "Park action failed\n");
460  return;
461  }
462 
463  if (ast_bridge_add_channel(parking_bridge, chan, NULL, 0, NULL)) {
464  astman_send_error(s, m, "Park action failed\n");
465  ao2_cleanup(parking_bridge);
466  return;
467  }
468 
469  astman_send_ack(s, m, "Park successful\n");
470  ao2_cleanup(parking_bridge);
471 }
472 
473 static void manager_park_bridged(struct mansession *s, const struct message *m,
474  struct ast_channel *chan, struct ast_channel *parker_chan,
475  const char *parkinglot, int timeout_override)
476 {
477  struct ast_bridge_channel *bridge_channel;
478  char *app_data;
479 
480  if (timeout_override != -1) {
481  if (ast_asprintf(&app_data, "%s,t(%d)", parkinglot, timeout_override) == -1) {
482  astman_send_error(s, m, "Park action failed\n");
483  return;
484  }
485  } else {
486  if (ast_asprintf(&app_data, "%s", parkinglot) == -1) {
487  astman_send_error(s, m, "Park action failed\n");
488  return;
489  }
490  }
491 
492  ast_channel_lock(parker_chan);
493  bridge_channel = ast_channel_get_bridge_channel(parker_chan);
494  ast_channel_unlock(parker_chan);
495 
496  if (!bridge_channel) {
497  ast_free(app_data);
498  astman_send_error(s, m, "Park action failed\n");
499  return;
500  }
501 
502  /* Subscribe to park messages for the channel being parked */
503  if (create_parked_subscription(parker_chan, ast_channel_uniqueid(chan), 1)) {
504  ast_free(app_data);
505  astman_send_error(s, m, "Park action failed\n");
506  ao2_cleanup(bridge_channel);
507  return;
508  }
509 
511  ast_channel_uniqueid(parker_chan), app_data);
512 
513  ast_free(app_data);
514 
515  astman_send_ack(s, m, "Park successful\n");
516  ao2_cleanup(bridge_channel);
517 }
518 
519 static int manager_park(struct mansession *s, const struct message *m)
520 {
521  const char *channel = astman_get_header(m, "Channel");
522  const char *timeout_channel = S_OR(astman_get_header(m, "TimeoutChannel"), astman_get_header(m, "Channel2"));
523  const char *announce_channel = astman_get_header(m, "AnnounceChannel");
524  const char *timeout = astman_get_header(m, "Timeout");
525  const char *parkinglot = astman_get_header(m, "Parkinglot");
526  char buf[BUFSIZ];
527  int timeout_override = -1;
528 
529  RAII_VAR(struct ast_channel *, parker_chan, NULL, ao2_cleanup);
531 
532  if (ast_strlen_zero(channel)) {
533  astman_send_error(s, m, "Channel not specified");
534  return 0;
535  }
536 
537  if (!ast_strlen_zero(timeout)) {
538  if (sscanf(timeout, "%30d", &timeout_override) != 1 || timeout_override < 0) {
539  astman_send_error(s, m, "Invalid Timeout value.");
540  return 0;
541  }
542 
543  if (timeout_override) {
544  /* If greater than zero, convert to seconds for internal use. Must be >= 1 second. */
545  timeout_override = MAX(1, timeout_override / 1000);
546  }
547  }
548 
549  if (!(chan = ast_channel_get_by_name(channel))) {
550  snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
551  astman_send_error(s, m, buf);
552  return 0;
553  }
554 
555  if (!ast_strlen_zero(timeout_channel)) {
557  ast_bridge_set_transfer_variables(chan, timeout_channel, 0);
559  }
560 
561  parker_chan = ast_channel_bridge_peer(chan);
562  if (!parker_chan || strcmp(ast_channel_name(parker_chan), timeout_channel)) {
563  if (!ast_strlen_zero(announce_channel)) {
564  struct ast_channel *announce_chan = ast_channel_get_by_name(announce_channel);
565  if (!announce_channel) {
566  astman_send_error(s, m, "AnnounceChannel does not exist");
567  return 0;
568  }
569 
570  create_parked_subscription(announce_chan, ast_channel_uniqueid(chan), 0);
571  ast_channel_cleanup(announce_chan);
572  }
573 
574  manager_park_unbridged(s, m, chan, parkinglot, timeout_override);
575  return 0;
576  }
577 
578  if (!ast_strlen_zero(announce_channel) && strcmp(announce_channel, timeout_channel)) {
579  /* When using an announce_channel in bridge mode, only add the announce channel if it isn't
580  * the same as the timeout channel (which will play announcements anyway) */
581  struct ast_channel *announce_chan = ast_channel_get_by_name(announce_channel);
582  if (!announce_channel) {
583  astman_send_error(s, m, "AnnounceChannel does not exist");
584  return 0;
585  }
586 
587  create_parked_subscription(announce_chan, ast_channel_uniqueid(chan), 0);
588  ast_channel_cleanup(announce_chan);
589  }
590 
591  manager_park_bridged(s, m, chan, parker_chan, parkinglot, timeout_override);
592  return 0;
593 }
594 
596 {
597  RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup);
598  RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
599 
600  if (!ast_parked_call_type()) {
601  return;
602  }
603 
604  payload = parked_call_payload_from_failure(parkee);
605  if (!payload) {
606  return;
607  }
608 
610  if (!msg) {
611  return;
612  }
613 
615 }
616 
618 {
619  RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup);
620  RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
621 
622  if (!ast_parked_call_type()) {
623  return;
624  }
625 
626  payload = parked_call_payload_from_parked_user(pu, event_type);
627  if (!payload) {
628  return;
629  }
630 
632  if (!msg) {
633  return;
634  }
635 
637 }
638 
640 {
641  char *event_type = "";
642  RAII_VAR(struct ast_str *, parked_call_string, NULL, ast_free);
643 
644  switch (parked_call->event_type) {
645  case PARKED_CALL:
646  event_type = "ParkedCall";
647  break;
648  case PARKED_CALL_TIMEOUT:
649  event_type = "ParkedCallTimeOut";
650  break;
651  case PARKED_CALL_GIVEUP:
652  event_type = "ParkedCallGiveUp";
653  break;
655  event_type = "UnParkedCall";
656  break;
657  case PARKED_CALL_SWAP:
658  event_type = "ParkedCallSwap";
659  break;
660  case PARKED_CALL_FAILED:
661  /* PARKED_CALL_FAILED doesn't currently get a message and is used exclusively for bridging */
662  return;
663  }
664 
665  parked_call_string = manager_build_parked_call_string(parked_call);
666  if (!parked_call_string) {
667  ast_log(LOG_ERROR, "Failed to issue an AMI event of '%s' in response to a stasis message.\n", event_type);
668  return;
669  }
670 
671  manager_event(EVENT_FLAG_CALL, event_type,
672  "%s",
673  ast_str_buffer(parked_call_string)
674  );
675 }
676 
678 {
679  if (stasis_message_type(message) == ast_parked_call_type()) {
680  struct ast_parked_call_payload *parked_call_message = stasis_message_data(message);
681  parked_call_message_response(parked_call_message);
682  }
683 }
684 
686 {
687  if (!parking_sub) {
691  }
692 }
693 
695 {
696  int res;
697 
702  return res ? -1 : 0;
703 }
704 
706 {
707  parking_sub = stasis_unsubscribe_and_join(parking_sub);
708 }
709 
711 {
712  ast_manager_unregister("Parkinglots");
713  ast_manager_unregister("ParkedCalls");
714  ast_manager_unregister("Park");
716 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
static int manager_park(struct mansession *s, const struct message *m)
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
int load_parking_manager(void)
Register manager actions and setup subscriptions for stasis events.
Asterisk main include file. File version handling, generic pbx functions.
static char parkinglot[AST_MAX_CONTEXT]
Definition: chan_mgcp.c:163
static void parking_manager_enable_stasis(void)
const char * id_text
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static struct ast_parked_call_payload * parked_call_payload_from_failure(struct ast_channel *chan)
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
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:3237
static int manager_parking_status(struct mansession *s, const struct message *m)
struct stasis_message_type * ast_parked_call_type(void)
accessor for the parked call stasis message type
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
struct ao2_container * parked_users
Definition: res_parking.h:95
static int timeout
Definition: cdr_mysql.c:86
unsigned int parkingtime
Definition: res_parking.h:69
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.
static int manager_parking_lot_list(struct mansession *s, const struct message *m)
Structure representing a snapshot of channel state.
unsigned int time_limit
Definition: res_parking.h:110
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.
#define EVENT_FLAG_CALL
Definition: manager.h:72
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
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:1079
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
Definition: muted.c:95
A parked call message payload.
Definition: parking.h:59
#define NULL
Definition: resample.c:96
const char * data
struct parking_lot * lot
Definition: res_parking.h:111
enum ast_parked_call_event_type event_type
Definition: parking.h:62
struct timeval start
Definition: res_parking.h:106
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.
long unsigned int duration
Definition: parking.h:64
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...
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:596
Utility functions.
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:269
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
void publish_parked_call_failure(struct ast_channel *parkee)
Publish a stasis parked call message for the channel indicating failure to park.
static void manager_parking_status_single_lot(struct mansession *s, const struct message *m, const char *id_text, const char *lot_name)
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:1065
Configuration File Parser.
#define ast_log
Definition: astobj2.c:42
#define MAX(a, b)
Definition: utils.h:228
struct ast_channel_snapshot * parkee
Definition: parking.h:60
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
#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:911
char * parker_dial_string
Definition: res_parking.h:109
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2992
int parking_space
Definition: res_parking.h:107
#define ao2_ref(o, delta)
Definition: astobj2.h:464
In case you didn&#39;t read that giant block of text above the mansession_session struct, the struct mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
Definition: manager.c:1625
static int manager_append_event_parking_lot_data_cb(void *obj, void *arg, void *data, int flags)
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)
#define stasis_subscribe(topic, callback, data)
Definition: stasis.h:652
const char * ast_channel_uniqueid(const struct ast_channel *chan)
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
Configuration option-handling.
Structure that contains information about a bridge.
Definition: bridge.h:357
static void parking_event_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
#define LOG_ERROR
Definition: logger.h:285
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:2519
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
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.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
unsigned int parkingspace
Definition: parking.h:65
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
long unsigned int timeout
Definition: parking.h:63
#define ao2_callback_data(container, flags, cb_fn, arg, data)
Definition: astobj2.h:1743
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
static struct ast_parked_call_payload * parked_call_payload_from_parked_user(struct parked_user *pu, enum ast_parked_call_event_type event_type)
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic&#39;s subscribers.
Definition: stasis.c:1511
#define ast_free(a)
Definition: astmm.h:182
ast_parked_call_event_type
Defines the type of parked call message being published.
Definition: parking.h:46
static void manager_park_unbridged(struct mansession *s, const struct message *m, struct ast_channel *chan, const char *parkinglot, int timeout_override)
void unload_parking_manager(void)
Unregister manager actions and remove subscriptions for stasis events.
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition: stasis.c:1136
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:4404
const ast_string_field name
Definition: res_parking.h:100
const ast_string_field parkinglot
Definition: parking.h:69
static struct stasis_subscription * parking_sub
subscription to the parking lot topic
struct ast_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel&#39;s bridge pointer.
Definition: channel.c:10783
struct stasis_topic * ast_parking_topic(void)
accessor for the parking stasis topic
Definition: parking.c:67
struct ast_channel * chan
Structure that contains information regarding a channel in a bridge.
FILE * out
Definition: utils/frame.c:33
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Standard Command Line Interface.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel&#39;s bridge peer only if the bridge is two-party.
Definition: channel.c:10765
const char * ast_channel_name(const struct ast_channel *chan)
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:1025
struct stasis_forward * sub
Definition: res_corosync.c:240
const ast_string_field parker_dial_string
Definition: parking.h:69
static int total
Definition: res_adsi.c:968
static void parking_manager_disable_stasis(void)
struct parking_lot * parking_lot_find_by_name(const char *lot_name)
Find a parking lot based on its name.
Definition: res_parking.c:601
Call Parking Resource Internal API.
Generic container type.
Call Parking and Pickup API Includes code and algorithms from the Zapata library. ...
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:186
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:248
struct ast_channel_snapshot * retriever
Definition: parking.h:61
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
Bridging API.
static void manager_parking_status_all_lots(struct mansession *s, const struct message *m, const char *id_text)
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
Asterisk module definitions.
struct ast_channel_snapshot * retriever
Definition: res_parking.h:105
struct ast_channel * chan
Definition: res_parking.h:104
static void parked_call_message_response(struct ast_parked_call_payload *parked_call)
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
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.
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
int create_parked_subscription(struct ast_channel *chan, const char *parkee_uuid, int hangup_after)
Create a parking announcement subscription.
struct parking_lot_cfg * cfg
Definition: res_parking.h:96
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:3201