Asterisk - The Open Source Telephony Project  18.5.0
command.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  * David M. Lee, II <[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 Stasis application command support.
22  *
23  * \author David M. Lee, II <[email protected]>
24  */
25 
26 #include "asterisk.h"
27 
28 #include "command.h"
29 
30 #include "asterisk/lock.h"
32 
37  void *data;
39  int retval;
40  unsigned int is_done:1;
41 };
42 
43 static void command_dtor(void *obj)
44 {
45  struct stasis_app_command *command = obj;
46 
47  if (command->data_destructor) {
48  command->data_destructor(command->data);
49  }
50 
51  ast_mutex_destroy(&command->lock);
52  ast_cond_destroy(&command->condition);
53 }
54 
57 {
58  struct stasis_app_command *command;
59 
60  command = ao2_alloc(sizeof(*command), command_dtor);
61  if (!command) {
62  if (data_destructor) {
63  data_destructor(data);
64  }
65  return NULL;
66  }
67 
68  ast_mutex_init(&command->lock);
69  ast_cond_init(&command->condition, 0);
70  command->callback = callback;
71  command->data = data;
73 
74  return command;
75 }
76 
77 void command_complete(struct stasis_app_command *command, int retval)
78 {
79  ast_mutex_lock(&command->lock);
80  command->is_done = 1;
81  command->retval = retval;
82  ast_cond_signal(&command->condition);
83  ast_mutex_unlock(&command->lock);
84 }
85 
86 int command_join(struct stasis_app_command *command)
87 {
88  int ret;
89 
90  ast_mutex_lock(&command->lock);
91  while (!command->is_done) {
92  ast_cond_wait(&command->condition, &command->lock);
93  }
94 
95  ret = command->retval;
96  ast_mutex_unlock(&command->lock);
97 
98  return ret;
99 }
100 
101 void command_invoke(struct stasis_app_command *command,
102  struct stasis_app_control *control, struct ast_channel *chan)
103 {
104  int retval = command->callback(control, chan, command->data);
105  if (command->data_destructor) {
106  command->data_destructor(command->data);
107  command->data_destructor = NULL;
108  }
109  command_complete(command, retval);
110 }
111 
112 static void command_queue_prestart_destroy(void *obj)
113 {
114  /* Clean up the container */
115  ao2_cleanup(obj);
116 }
117 
119  .type = "stasis-command-prestart-queue",
121 };
122 
125 {
126  struct ast_datastore *datastore;
127  struct ao2_container *command_queue;
128  RAII_VAR(struct stasis_app_command *, command,
129  command_create(command_fn, data, data_destructor), ao2_cleanup);
130 
131  if (!command) {
132  return -1;
133  }
134 
135  datastore = ast_channel_datastore_find(chan, &command_queue_prestart, NULL);
136  if (datastore) {
137  command_queue = datastore->data;
138  ao2_link(command_queue, command);
139  return 0;
140  }
141 
143  if (!command_queue) {
144  return -1;
145  }
146 
147  datastore = ast_datastore_alloc(&command_queue_prestart, NULL);
148  if (!datastore) {
149  ao2_cleanup(command_queue);
150  return -1;
151  }
152  ast_channel_datastore_add(chan, datastore);
153 
154  datastore->data = command_queue;
155  ao2_link(command_queue, command);
156 
157  return 0;
158 }
159 
161 {
162  struct ast_datastore *datastore = ast_channel_datastore_find(chan, &command_queue_prestart, NULL);
163 
164  if (!datastore) {
165  return NULL;
166  }
167 
168  return ao2_bump(datastore->data);
169 }
const char * type
Definition: datastore.h:32
Main Channel structure associated with a channel.
Asterisk locking-related definitions:
int command_prestart_queue_command(struct ast_channel *chan, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor)
Queue a Stasis() prestart command for a channel.
Definition: command.c:123
Asterisk main include file. File version handling, generic pbx functions.
void command_complete(struct stasis_app_command *command, int retval)
Definition: command.c:77
Internal API for the Stasis application commands.
static const struct ast_datastore_info command_queue_prestart
Definition: command.c:118
unsigned int is_done
Definition: command.c:40
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1335
Structure for a data store type.
Definition: datastore.h:31
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
#define ast_cond_init(cond, attr)
Definition: lock.h:199
struct ao2_container * command_prestart_get_container(struct ast_channel *chan)
Get the Stasis() prestart commands for a channel.
Definition: command.c:160
#define ast_mutex_lock(a)
Definition: lock.h:187
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
#define NULL
Definition: resample.c:96
void command_invoke(struct stasis_app_command *command, struct stasis_app_control *control, struct ast_channel *chan)
Definition: command.c:101
command_data_destructor_fn data_destructor
Definition: command.c:38
#define ast_cond_signal(cond)
Definition: lock.h:201
pthread_cond_t ast_cond_t
Definition: lock.h:176
int(* stasis_app_command_cb)(struct stasis_app_control *control, struct ast_channel *chan, void *data)
static void command_dtor(void *obj)
Definition: command.c:43
#define ao2_bump(obj)
Definition: astobj2.h:491
#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
void(* command_data_destructor_fn)(void *data)
Typedef for data destructor for stasis app commands.
ast_mutex_t lock
Definition: command.c:34
Backend API for implementing components of res_stasis.
struct stasis_app_command * command_create(stasis_app_command_cb callback, void *data, command_data_destructor_fn data_destructor)
Definition: command.c:55
#define ast_cond_destroy(cond)
Definition: lock.h:200
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
int command_join(struct stasis_app_command *command)
Definition: command.c:86
void * data
Definition: datastore.h:70
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
ast_cond_t condition
Definition: command.c:35
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
#define ast_mutex_init(pmutex)
Definition: lock.h:184
Generic container type.
#define ast_mutex_destroy(a)
Definition: lock.h:186
stasis_app_command_cb callback
Definition: command.c:36
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390
Structure for mutex and tracking information.
Definition: lock.h:135
#define ast_mutex_unlock(a)
Definition: lock.h:188
static void command_queue_prestart_destroy(void *obj)
Definition: command.c:112
#define ao2_link(container, obj)
Definition: astobj2.h:1549