-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrayo_components.c
262 lines (242 loc) · 8.55 KB
/
rayo_components.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/*
* mod_rayo for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013, Grasshopper
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mod_rayo for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is Grasshopper
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Chris Rienzo <chris.rienzo@grasshopper.com>
*
* rayo_components.c -- Rayo component interface
*
*/
#include "rayo_components.h"
#include <switch.h>
#include "mod_rayo.h"
#include "iks_helpers.h"
/**
* Get access to Rayo component data.
* @param id the component internal ID
* @return the component or NULL. Call rayo_component_unlock() when done with component pointer.
*/
struct rayo_component *rayo_component_locate(const char *id, const char *file, int line)
{
struct rayo_actor *actor = rayo_actor_locate_by_id(id, file, line);
if (actor && is_component_actor(actor)) {
return RAYO_COMPONENT(actor);
} else if (actor) {
RAYO_RELEASE(actor);
}
return NULL;
}
/**
* Send component start reply
* @param component the component
* @param iq the start request
*/
void rayo_component_send_start(struct rayo_component *component, iks *iq)
{
iks *response = iks_new_iq_result(iq);
iks *ref = iks_insert(response, "ref");
iks_insert_attrib(ref, "xmlns", RAYO_NS);
iks_insert_attrib_printf(ref, "uri", "xmpp:%s", RAYO_JID(component));
RAYO_SEND_REPLY(component, iks_find_attrib(response, "to"), response);
}
/**
* Create component complete event
* @param component the component
* @param reason_str the completion reason
* @param reason_namespace the completion reason namespace
* @param meta metadata to add as child
* @param child_of_complete if true metadata is child of complete instead of reason
* @return the event
*/
iks *rayo_component_create_complete_event_with_metadata(struct rayo_component *component, const char *reason_str, const char *reason_namespace, iks *meta, int child_of_complete)
{
iks *response = iks_new("presence");
iks *complete;
iks *reason;
iks_insert_attrib(response, "from", RAYO_JID(component));
iks_insert_attrib(response, "to", component->client_jid);
iks_insert_attrib(response, "type", "unavailable");
complete = iks_insert(response, "complete");
iks_insert_attrib(complete, "xmlns", RAYO_EXT_NS);
reason = iks_insert(complete, reason_str);
iks_insert_attrib(reason, "xmlns", reason_namespace);
if (meta) {
meta = iks_copy_within(meta, iks_stack(response));
if (child_of_complete) {
iks_insert_node(complete, meta);
} else {
iks_insert_node(reason, meta);
}
}
return response;
}
/**
* Create component complete event
* @param component the component
* @param reason the completion reason
* @param reason_namespace the completion reason namespace
* @return the event
*/
iks *rayo_component_create_complete_event(struct rayo_component *component, const char *reason, const char *reason_namespace)
{
return rayo_component_create_complete_event_with_metadata(component, reason, reason_namespace, NULL, 0);
}
/**
* Send rayo component complete event
*/
void rayo_component_send_complete_event(struct rayo_component *component, iks *response)
{
component->complete = 1;
RAYO_SEND_REPLY(component, iks_find_attrib(response, "to"), response);
RAYO_RELEASE(component);
RAYO_DESTROY(component);
}
/**
* Send rayo complete
*/
void rayo_component_send_complete(struct rayo_component *component, const char *reason, const char *reason_namespace)
{
rayo_component_send_complete_event(component, rayo_component_create_complete_event(component, reason, reason_namespace));
}
/**
* Send rayo complete
*/
void rayo_component_send_complete_with_metadata(struct rayo_component *component, const char *reason, const char *reason_namespace, iks *meta, int child_of_complete)
{
rayo_component_send_complete_event(component, rayo_component_create_complete_event_with_metadata(component, reason, reason_namespace, meta, child_of_complete));
}
/**
* Send rayo complete
*/
void rayo_component_send_complete_with_metadata_string(struct rayo_component *component, const char *reason, const char *reason_namespace, const char *meta, int child_of_complete)
{
iks *meta_xml = NULL;
iksparser *p = iks_dom_new(&meta_xml);
if (iks_parse(p, meta, 0, 1) != IKS_OK) {
/* unexpected ... */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "%s Failed to parse metadata for complete event: %s\n",
RAYO_JID(component), meta);
/* send without... */
rayo_component_send_complete(component, reason, reason_namespace);
} else {
rayo_component_send_complete_with_metadata(component, reason, reason_namespace, meta_xml, child_of_complete);
}
if (meta_xml) {
iks_delete(meta_xml);
}
iks_parser_delete(p);
}
/**
* Background API data
*/
struct component_bg_api_cmd {
const char *cmd;
const char *args;
switch_memory_pool_t *pool;
struct rayo_component *component;
};
/**
* Thread that outputs to component
* @param thread this thread
* @param obj the Rayo mixer context
* @return NULL
*/
static void *SWITCH_THREAD_FUNC component_bg_api_thread(switch_thread_t *thread, void *obj)
{
struct component_bg_api_cmd *cmd = (struct component_bg_api_cmd *)obj;
switch_stream_handle_t stream = { 0 };
switch_memory_pool_t *pool = cmd->pool;
SWITCH_STANDARD_STREAM(stream);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "BGAPI EXEC: %s %s\n", cmd->cmd, cmd->args);
if (switch_api_execute(cmd->cmd, cmd->args, NULL, &stream) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "BGAPI EXEC FAILURE\n");
rayo_component_send_complete(cmd->component, COMPONENT_COMPLETE_ERROR);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "BGAPI EXEC RESULT: %s\n", (char *)stream.data);
}
switch_safe_free(stream.data);
switch_core_destroy_memory_pool(&pool);
return NULL;
}
/**
* Run a background API command
* @param cmd API command
* @param args API args
*/
void rayo_component_api_execute_async(struct rayo_component *component, const char *cmd, const char *args)
{
switch_thread_t *thread;
switch_threadattr_t *thd_attr = NULL;
struct component_bg_api_cmd *bg_cmd = NULL;
switch_memory_pool_t *pool;
/* set up command */
switch_core_new_memory_pool(&pool);
bg_cmd = switch_core_alloc(pool, sizeof(*bg_cmd));
bg_cmd->pool = pool;
bg_cmd->cmd = switch_core_strdup(pool, cmd);
bg_cmd->args = switch_core_strdup(pool, args);
bg_cmd->component = component;
/* create thread */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s BGAPI START\n", RAYO_JID(component));
switch_threadattr_create(&thd_attr, pool);
switch_threadattr_detach_set(thd_attr, 1);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
switch_thread_create(&thread, thd_attr, component_bg_api_thread, bg_cmd, pool);
}
/**
* Handle configuration
*/
switch_status_t rayo_components_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool, const char *config_file)
{
if (rayo_input_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS ||
rayo_output_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS ||
rayo_prompt_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS ||
rayo_record_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS ||
rayo_fax_components_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS ||
rayo_exec_component_load(module_interface, pool, config_file) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_TERM;
}
return SWITCH_STATUS_SUCCESS;
}
/**
* Handle shutdown
*/
switch_status_t rayo_components_shutdown(void)
{
rayo_input_component_shutdown();
rayo_output_component_shutdown();
rayo_prompt_component_shutdown();
rayo_record_component_shutdown();
rayo_fax_components_shutdown();
rayo_exec_component_shutdown();
return SWITCH_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet
*/