Asterisk - The Open Source Telephony Project GIT-master-57e2743
Loading...
Searching...
No Matches
res_manager_devicestate.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2014, Digium, Inc.
5 *
6 * Mark Michelson <mmichelson@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/*** MODULEINFO
20 <support_level>core</support_level>
21 ***/
22
23/*** DOCUMENTATION
24 <manager name="DeviceStateList" language="en_US">
25 <since>
26 <version>13.0.0</version>
27 </since>
28 <synopsis>
29 List the current known device states.
30 </synopsis>
31 <syntax>
32 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
33 </syntax>
34 <description>
35 <para>This will list out all known device states in a
36 sequence of <replaceable>DeviceStateChange</replaceable> events.
37 When finished, a <replaceable>DeviceStateListComplete</replaceable> event
38 will be emitted.</para>
39 </description>
40 <see-also>
41 <ref type="managerEvent">DeviceStateChange</ref>
42 <ref type="function">DEVICE_STATE</ref>
43 </see-also>
44 <responses>
45 <list-elements>
46 <xi:include xpointer="xpointer(/docs/managerEvent[@name='DeviceStateChange'])" />
47 </list-elements>
48 <managerEvent name="DeviceStateListComplete" language="en_US">
49 <managerEventInstance class="EVENT_FLAG_COMMAND">
50 <since>
51 <version>13.0.0</version>
52 </since>
53 <synopsis>
54 Indicates the end of the list the current known extension states.
55 </synopsis>
56 <syntax>
57 <parameter name="EventList">
58 <para>Conveys the status of the event list.</para>
59 </parameter>
60 <parameter name="ListItems">
61 <para>Conveys the number of statuses reported.</para>
62 </parameter>
63 </syntax>
64 </managerEventInstance>
65 </managerEvent>
66 </responses>
67 </manager>
68 <manager name="DeviceStateChange" language="en_US">
69 <since>
70 <version>24.1.0</version>
71 <version>23.7.0</version>
72 <version>22.13.0</version>
73 <version>20.23.0</version>
74 </since>
75 <synopsis>
76 Set a device state
77 </synopsis>
78 <syntax>
79 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
80 <parameter name="Device" required="true">
81 <para>Device name. Does not need to be Custom; however, set device states for non-Custom devices with caution.</para>
82 </parameter>
83 <parameter name="State" required="true">
84 <para>The new device state value.</para>
85 <para>Should be one of the following:</para>
86 <para>The possible values are:</para>
87 <para>UNKNOWN | NOT_INUSE | INUSE | BUSY | INVALID | UNAVAILABLE | RINGING | RINGINUSE | ONHOLD</para>
88 </parameter>
89 <parameter name="Cachable" required="false">
90 <para>Whether or not this device state is cachable. Default is true, which is needed to persist the update.</para>
91 </parameter>
92 <parameter name="EntityID" required="true">
93 <para>The Entity ID of the remote Asterisk system that originated this device state update.</para>
94 <para>If the Entity ID provided matches the local Asterisk system's Entity ID, the update will be rejected.</para>
95 </parameter>
96 </syntax>
97 <description>
98 <para>Sets a device state value.</para>
99 <para>This can be used to manually synchronize the device state of remote devices.
100 It should NOT be used to set the device state of local devices.</para>
101 </description>
102 <see-also>
103 <ref type="manager">MailboxStateChange</ref>
104 </see-also>
105 </manager>
106 <manager name="MailboxStateChange" language="en_US">
107 <since>
108 <version>24.1.0</version>
109 <version>23.7.0</version>
110 <version>22.13.0</version>
111 <version>20.23.0</version>
112 </since>
113 <synopsis>
114 Set mailbox state
115 </synopsis>
116 <syntax>
117 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
118 <parameter name="Mailbox" required="true">
119 <para>The name of the mailbox (with optional context).</para>
120 </parameter>
121 <parameter name="NewMessages" required="true">
122 <para>The number of new messages.</para>
123 </parameter>
124 <parameter name="OldMessages" required="true">
125 <para>The number of old messages.</para>
126 </parameter>
127 <parameter name="EntityID" required="true">
128 <para>The Entity ID of the remote Asterisk system that originated this mailbox state update.</para>
129 <para>If the Entity ID provided matches the local Asterisk system's Entity ID, the update will be rejected.</para>
130 </parameter>
131 </syntax>
132 <description>
133 <para>Sets a mailbox's state.</para>
134 <para>This can be used to manually synchronize the mailbox state of remote mailboxes.
135 It should NOT be used to set the mailbox state of local mailboxes.</para>
136 <para>Note this differs from the <literal>MWIUpdate</literal> action, which is more heavyweight
137 and depends on <literal>res_mwi_external</literal>.</para>
138 </description>
139 <see-also>
140 <ref type="manager">DeviceStateChange</ref>
141 <ref type="manager">MWIUpdate</ref>
142 </see-also>
143 </manager>
144 ***/
145
146
147#include "asterisk.h"
148#include "asterisk/module.h"
149#include "asterisk/manager.h"
150#include "asterisk/stasis.h"
151#include "asterisk/devicestate.h"
152#include "asterisk/mwi.h"
153#include "asterisk/conversions.h"
154
156
157static int action_devicestatelist(struct mansession *s, const struct message *m)
158{
159 RAII_VAR(struct ao2_container *, device_states, NULL, ao2_cleanup);
160 const char *action_id = astman_get_header(m, "ActionID");
161 struct stasis_message *msg;
162 struct ao2_iterator it_states;
163 int count = 0;
164
167 if (!device_states) {
168 astman_send_error(s, m, "Memory Allocation Failure");
169 return 0;
170 }
171
172 astman_send_listack(s, m, "Device State Changes will follow", "start");
173
174 it_states = ao2_iterator_init(device_states, 0);
175 for (; (msg = ao2_iterator_next(&it_states)); ao2_ref(msg, -1)) {
177
178 if (!blob) {
179 continue;
180 }
181
182 count++;
183
184 astman_append(s, "Event: %s\r\n", blob->manager_event);
185 if (!ast_strlen_zero(action_id)) {
186 astman_append(s, "ActionID: %s\r\n", action_id);
187 }
188 astman_append(s, "%s\r\n", blob->extra_fields);
189 ao2_ref(blob, -1);
190 }
191 ao2_iterator_destroy(&it_states);
192
193 astman_send_list_complete_start(s, m, "DeviceStateListComplete", count);
195
196 return 0;
197}
198
199static int action_devicestatechange(struct mansession *s, const struct message *m)
200{
201 struct ast_eid eid;
202 enum ast_device_state state_val;
203 const char *device = astman_get_header(m, "Device");
204 const char *state = astman_get_header(m, "State");
205 const char *cachable = astman_get_header(m, "Cachable");
206 const char *entity_id = astman_get_header(m, "EntityID");
207
208 if (ast_strlen_zero(device) || ast_strlen_zero(state)) {
209 astman_send_error(s, m, "Missing device or device state");
210 return 0;
211 }
212 if (ast_strlen_zero(entity_id) || ast_str_to_eid(&eid, entity_id)) {
213 astman_send_error(s, m, "Missing or invalid entity ID");
214 return 0;
215 }
216 if (!strchr(device, '/') && !strchr(device, ':')) {
217 astman_send_error(s, m, "Invalid device name");
218 return 0;
219 }
220
221 state_val = ast_devstate_val(state);
222 /* ast_devstate_val returns AST_DEVICE_UNKNOWN if the device state value is not valid,
223 * but AST_DEVICE_UNKNOWN is also a legitimate value, so allow it if that's what the input actually was. */
224 if (state_val == AST_DEVICE_UNKNOWN && strcasecmp(state, "UNKNOWN")) {
225 astman_send_error(s, m, "Invalid device state value");
226 return 0;
227 }
228
230 astman_send_error(s, m, "Entity ID is ourself (must be from a different Asterisk system)");
231 return 0;
232 }
233
235 astman_send_error(s, m, "Failed to publish device state update");
236 return 0;
237 }
238
239 astman_send_ack(s, m, "Updated or set device state");
240 return 0;
241}
242
243static int action_mailboxstatechange(struct mansession *s, const struct message *m)
244{
245 struct ast_eid eid;
246 int new_msgs, old_msgs;
247 char *context, *mailbox;
248 const char *mbox = astman_get_header(m, "Mailbox");
249 const char *newmsgs = astman_get_header(m, "NewMessages");
250 const char *oldmsgs = astman_get_header(m, "OldMessages");
251 const char *entity_id = astman_get_header(m, "EntityID");
252
253 if (ast_strlen_zero(mbox) || ast_strlen_zero(newmsgs) || ast_strlen_zero(oldmsgs)) {
254 astman_send_error(s, m, "Missing required parameters");
255 return 0;
256 }
257 if (ast_strlen_zero(entity_id) || ast_str_to_eid(&eid, entity_id)) {
258 astman_send_error(s, m, "Missing or invalid entity ID");
259 return 0;
260 }
261
262 if (ast_str_to_int(newmsgs, &new_msgs) || ast_str_to_int(oldmsgs, &old_msgs)) {
263 astman_send_error(s, m, "Invalid mailbox counts");
264 return 0;
265 }
266 if (new_msgs < 0 || old_msgs < 0) {
267 astman_send_error(s, m, "Invalid mailbox counts (must be non-negative)");
268 return 0;
269 }
270
272 astman_send_error(s, m, "Entity ID is ourself (must be from a different Asterisk system)");
273 return 0;
274 }
275
276 context = ast_strdupa(mbox);
277 mailbox = strsep(&context, "@");
278
279 /* Mailbox is mandatory, context is optional */
280 if (ast_strlen_zero(mailbox)) {
281 astman_send_error(s, m, "A mailbox is required");
282 return 0;
283 }
284
285 if (ast_publish_mwi_state_full(mailbox, context, new_msgs, old_msgs, NULL, &eid)) {
286 astman_send_error(s, m, "Failed to publish mailbox state update");
287 return 0;
288 }
289
290 astman_send_ack(s, m, "Updated mailbox state");
291 return 0;
292}
293
294static int unload_module(void)
295{
297 ast_manager_unregister("DeviceStateList");
298 ast_manager_unregister("DeviceStateChange");
299 ast_manager_unregister("MailboxStateChange");
300
301 return 0;
302}
303
342
343AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Manager Device State Topic Forwarder",
344 .support_level = AST_MODULE_SUPPORT_CORE,
345 .load = load_module,
346 .unload = unload_module,
static const char * mbox(struct ast_vm_user *vmu, int id)
char * strsep(char **str, const char *delims)
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
#define ast_log
Definition astobj2.c:42
#define ao2_iterator_next(iter)
Definition astobj2.h:1911
#define ao2_cleanup(obj)
Definition astobj2.h:1934
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.
Conversion utility functions.
int ast_str_to_int(const char *str, int *res)
Convert the given string to a signed integer.
Definition conversions.c:44
Device state management.
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
@ AST_DEVSTATE_CACHABLE
Definition devicestate.h:70
@ AST_DEVSTATE_NOT_CACHABLE
Definition devicestate.h:69
struct stasis_cache * ast_device_state_cache(void)
Backend cache for ast_device_state_topic_cached()
struct stasis_topic * ast_device_state_topic_all(void)
Get the Stasis topic for device state messages.
enum ast_device_state ast_devstate_val(const char *val)
Convert device state from text to integer value.
ast_device_state
Device States.
Definition devicestate.h:52
@ AST_DEVICE_UNKNOWN
Definition devicestate.h:53
int ast_publish_device_state_full(const char *device, enum ast_device_state state, enum ast_devstate_cache cachable, struct ast_eid *eid)
Publish a device state update with EID.
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:1963
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition manager.c:1921
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:1999
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
Definition manager.c:441
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition manager.c:1953
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition manager.c:1582
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition manager.c:2007
void astman_append(struct mansession *s, const char *fmt,...)
Definition manager.c:1842
static struct stasis_topic * manager_topic
A stasis_topic that all topics AMI cares about will be forwarded to.
Definition manager.c:170
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition manager.c:7782
#define LOG_ERROR
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define EVENT_FLAG_REPORTING
Definition manager.h:84
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition manager.h:193
#define EVENT_FLAG_CALL
Definition manager.h:76
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition module.h:331
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition module.h:557
@ AST_MODPRI_DEVSTATE_CONSUMER
Definition module.h:347
@ AST_MODULE_SUPPORT_CORE
Definition module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition module.h:78
Asterisk MWI API.
int ast_publish_mwi_state_full(const char *mailbox, const char *context, int new_msgs, int old_msgs, const char *channel_id, struct ast_eid *eid)
Publish a MWI state update via stasis with all parameters.
Definition mwi.c:393
static int action_devicestatelist(struct mansession *s, const struct message *m)
static int action_mailboxstatechange(struct mansession *s, const struct message *m)
static int action_devicestatechange(struct mansession *s, const struct message *m)
static int load_module(void)
static int unload_module(void)
static struct stasis_forward * topic_forwarder
#define NULL
Definition resample.c:96
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
struct ast_manager_event_blob * stasis_message_to_ami(struct stasis_message *msg)
Build the AMI representation of the message.
struct stasis_forward * stasis_forward_cancel(struct stasis_forward *forward)
Definition stasis.c:1626
struct ao2_container * stasis_cache_dump_by_eid(struct stasis_cache *cache, struct stasis_message_type *type, const struct ast_eid *eid)
Dump cached items to a subscription for a specific entity.
struct stasis_forward * stasis_forward_all(struct stasis_topic *from_topic, struct stasis_topic *to_topic)
Create a subscription which forwards all messages from one topic to another.
Definition stasis.c:1656
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
Definition utils.c:2250
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
An Entity ID is essentially a MAC address, brief and unique.
Definition utils.h:853
unsigned char eid[6]
Definition utils.h:854
Struct containing info for an AMI event to send out.
Definition manager.h:504
const ast_string_field extra_fields
Definition manager.h:509
const char * manager_event
Definition manager.h:506
In case you didn't read that giant block of text above the mansession_session struct,...
Definition manager.c:314
Forwarding information.
Definition stasis.c:1609
#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:981
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition utils.c:3128
int ast_eid_is_empty(const struct ast_eid *eid)
Check if EID is empty.
Definition utils.c:3133
struct ast_eid ast_eid_default
Global EID.
Definition options.c:94
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
Definition utils.c:3111