1 /*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2010, Mathieu Parent <math.parent@gmail.com>
4 *
5 * Version: MPL 1.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18 *
19 * The Initial Developer of the Original Code is
20 * Mathieu Parent <math.parent@gmail.com>
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Mathieu Parent <math.parent@gmail.com>
27 *
28 *
29 * skinny_api.c -- Skinny Call Control Protocol (SCCP) Endpoint Module
30 *
31 */
32
33 #include <switch.h>
34 #include "mod_skinny.h"
35 #include "skinny_protocol.h"
36 #include "skinny_tables.h"
37
38 /*****************************************************************************/
39 /* skinny_api_list_* */
40 /*****************************************************************************/
41
skinny_api_list_profiles(const char * line,const char * cursor,switch_console_callback_match_t ** matches)42 static switch_status_t skinny_api_list_profiles(const char *line, const char *cursor, switch_console_callback_match_t **matches)
43 {
44 switch_console_callback_match_t *my_matches = NULL;
45 switch_status_t status = SWITCH_STATUS_FALSE;
46 switch_hash_index_t *hi;
47 void *val;
48 skinny_profile_t *profile;
49
50 /* walk profiles */
51 switch_mutex_lock(skinny_globals.mutex);
52 for (hi = switch_core_hash_first(skinny_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) {
53 switch_core_hash_this(hi, NULL, NULL, &val);
54 profile = (skinny_profile_t *) val;
55
56 switch_console_push_match(&my_matches, profile->name);
57 }
58 switch_mutex_unlock(skinny_globals.mutex);
59
60 if (my_matches) {
61 *matches = my_matches;
62 status = SWITCH_STATUS_SUCCESS;
63 }
64
65 return status;
66 }
67
68 struct match_helper {
69 switch_console_callback_match_t *my_matches;
70 };
71
skinny_api_list_devices_callback(void * pArg,int argc,char ** argv,char ** columnNames)72 static int skinny_api_list_devices_callback(void *pArg, int argc, char **argv, char **columnNames)
73 {
74 struct match_helper *h = (struct match_helper *) pArg;
75 char *device_name = argv[0];
76
77 switch_console_push_match(&h->my_matches, device_name);
78 return 0;
79 }
80
skinny_api_list_devices(const char * line,const char * cursor,switch_console_callback_match_t ** matches)81 static switch_status_t skinny_api_list_devices(const char *line, const char *cursor, switch_console_callback_match_t **matches)
82 {
83 struct match_helper h = { 0 };
84 switch_status_t status = SWITCH_STATUS_FALSE;
85 skinny_profile_t *profile = NULL;
86 char *sql;
87
88 char *myline;
89 char *argv[1024] = { 0 };
90 int argc = 0;
91
92 if (!(myline = strdup(line))) {
93 status = SWITCH_STATUS_MEMERR;
94 return status;
95 }
96 if (!(argc = switch_separate_string(myline, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) || argc < 4) {
97 switch_safe_free(myline);
98 return status;
99 }
100
101 if(!strcasecmp(argv[1], "profile")) {/* skinny profile <profile_name> ... */
102 profile = skinny_find_profile(argv[2]);
103 } else if(!strcasecmp(argv[2], "profile")) {/* skinny status profile <profile_name> ... */
104 profile = skinny_find_profile(argv[3]);
105 }
106
107 if(profile) {
108 if ((sql = switch_mprintf("SELECT name FROM skinny_devices"))) {
109 skinny_execute_sql_callback(profile, profile->sql_mutex, sql, skinny_api_list_devices_callback, &h);
110 switch_safe_free(sql);
111 }
112 }
113
114 if (h.my_matches) {
115 *matches = h.my_matches;
116 status = SWITCH_STATUS_SUCCESS;
117 }
118
119 switch_safe_free(myline);
120
121 return status;
122 }
123
skinny_api_list_reset_types(const char * line,const char * cursor,switch_console_callback_match_t ** matches)124 static switch_status_t skinny_api_list_reset_types(const char *line, const char *cursor, switch_console_callback_match_t **matches)
125 {
126 switch_status_t status = SWITCH_STATUS_FALSE;
127 SKINNY_PUSH_DEVICE_RESET_TYPES
128 return status;
129 }
130
skinny_api_list_stimuli(const char * line,const char * cursor,switch_console_callback_match_t ** matches)131 static switch_status_t skinny_api_list_stimuli(const char *line, const char *cursor, switch_console_callback_match_t **matches)
132 {
133 switch_status_t status = SWITCH_STATUS_FALSE;
134 SKINNY_PUSH_STIMULI
135 return status;
136 }
137
skinny_api_list_ring_types(const char * line,const char * cursor,switch_console_callback_match_t ** matches)138 static switch_status_t skinny_api_list_ring_types(const char *line, const char *cursor, switch_console_callback_match_t **matches)
139 {
140 switch_status_t status = SWITCH_STATUS_FALSE;
141 SKINNY_PUSH_RING_TYPES
142 return status;
143 }
144
skinny_api_list_ring_modes(const char * line,const char * cursor,switch_console_callback_match_t ** matches)145 static switch_status_t skinny_api_list_ring_modes(const char *line, const char *cursor, switch_console_callback_match_t **matches)
146 {
147 switch_status_t status = SWITCH_STATUS_FALSE;
148 SKINNY_PUSH_RING_MODES
149 return status;
150 }
151
skinny_api_list_stimulus_instances(const char * line,const char * cursor,switch_console_callback_match_t ** matches)152 static switch_status_t skinny_api_list_stimulus_instances(const char *line, const char *cursor, switch_console_callback_match_t **matches)
153 {
154 switch_status_t status = SWITCH_STATUS_FALSE;
155 switch_console_callback_match_t *my_matches = NULL;
156
157 switch_console_push_match(&my_matches, "<stimulus_instance>");
158 switch_console_push_match(&my_matches, "0");
159
160 if (my_matches) {
161 *matches = my_matches;
162 status = SWITCH_STATUS_SUCCESS;
163 }
164 return status;
165 }
166
skinny_api_list_stimulus_modes(const char * line,const char * cursor,switch_console_callback_match_t ** matches)167 static switch_status_t skinny_api_list_stimulus_modes(const char *line, const char *cursor, switch_console_callback_match_t **matches)
168 {
169 switch_status_t status = SWITCH_STATUS_FALSE;
170 SKINNY_PUSH_LAMP_MODES
171 return status;
172 }
173
skinny_api_list_speaker_modes(const char * line,const char * cursor,switch_console_callback_match_t ** matches)174 static switch_status_t skinny_api_list_speaker_modes(const char *line, const char *cursor, switch_console_callback_match_t **matches)
175 {
176 switch_status_t status = SWITCH_STATUS_FALSE;
177 SKINNY_PUSH_SPEAKER_MODES
178 return status;
179 }
180
skinny_api_list_call_states(const char * line,const char * cursor,switch_console_callback_match_t ** matches)181 static switch_status_t skinny_api_list_call_states(const char *line, const char *cursor, switch_console_callback_match_t **matches)
182 {
183 switch_status_t status = SWITCH_STATUS_FALSE;
184 SKINNY_PUSH_CALL_STATES
185 return status;
186 }
187
skinny_api_list_line_instances(const char * line,const char * cursor,switch_console_callback_match_t ** matches)188 static switch_status_t skinny_api_list_line_instances(const char *line, const char *cursor, switch_console_callback_match_t **matches)
189 {
190 switch_status_t status = SWITCH_STATUS_FALSE;
191 switch_console_callback_match_t *my_matches = NULL;
192
193 /* TODO */
194 switch_console_push_match(&my_matches, "1");
195 switch_console_push_match(&my_matches, "<line_instance>");
196
197 if (my_matches) {
198 *matches = my_matches;
199 status = SWITCH_STATUS_SUCCESS;
200 }
201 return status;
202 }
203
skinny_api_list_call_ids(const char * line,const char * cursor,switch_console_callback_match_t ** matches)204 static switch_status_t skinny_api_list_call_ids(const char *line, const char *cursor, switch_console_callback_match_t **matches)
205 {
206 switch_status_t status = SWITCH_STATUS_FALSE;
207 switch_console_callback_match_t *my_matches = NULL;
208
209 /* TODO */
210 switch_console_push_match(&my_matches, "1345");
211 switch_console_push_match(&my_matches, "<call_id>");
212
213 if (my_matches) {
214 *matches = my_matches;
215 status = SWITCH_STATUS_SUCCESS;
216 }
217 return status;
218 }
219
skinny_api_list_settings(const char * line,const char * cursor,switch_console_callback_match_t ** matches)220 static switch_status_t skinny_api_list_settings(const char *line, const char *cursor, switch_console_callback_match_t **matches)
221 {
222 switch_status_t status = SWITCH_STATUS_FALSE;
223 switch_console_callback_match_t *my_matches = NULL;
224
225 switch_console_push_match(&my_matches, "domain");
226 switch_console_push_match(&my_matches, "ip");
227 switch_console_push_match(&my_matches, "port");
228 switch_console_push_match(&my_matches, "patterns-dialplan");
229 switch_console_push_match(&my_matches, "patterns-context");
230 switch_console_push_match(&my_matches, "dialplan");
231 switch_console_push_match(&my_matches, "context");
232 switch_console_push_match(&my_matches, "keep-alive");
233 switch_console_push_match(&my_matches, "date-format");
234 switch_console_push_match(&my_matches, "odbc-dsn");
235 switch_console_push_match(&my_matches, "debug");
236 switch_console_push_match(&my_matches, "auto-restart");
237 switch_console_push_match(&my_matches, "ext-voicemail");
238 switch_console_push_match(&my_matches, "ext-redial");
239 switch_console_push_match(&my_matches, "ext-meetme");
240 switch_console_push_match(&my_matches, "ext-pickup");
241 switch_console_push_match(&my_matches, "ext-cfwdall");
242
243 if (my_matches) {
244 *matches = my_matches;
245 status = SWITCH_STATUS_SUCCESS;
246 }
247 return status;
248 }
249
250 /*****************************************************************************/
251 /* skinny_api_cmd_* */
252 /*****************************************************************************/
skinny_api_cmd_status_profile(const char * profile_name,switch_stream_handle_t * stream)253 static switch_status_t skinny_api_cmd_status_profile(const char *profile_name, switch_stream_handle_t *stream)
254 {
255 skinny_profile_t *profile;
256 if ((profile = skinny_find_profile(profile_name))) {
257 skinny_profile_dump(profile, stream);
258 } else {
259 stream->write_function(stream, "Profile not found!\n");
260 }
261
262 return SWITCH_STATUS_SUCCESS;
263 }
264
skinny_api_cmd_status_profile_device(const char * profile_name,const char * device_name,switch_stream_handle_t * stream)265 static switch_status_t skinny_api_cmd_status_profile_device(const char *profile_name, const char *device_name, switch_stream_handle_t *stream)
266 {
267 skinny_profile_t *profile;
268 if ((profile = skinny_find_profile(profile_name))) {
269 dump_device(profile, device_name, stream);
270 } else {
271 stream->write_function(stream, "Profile not found!\n");
272 }
273
274 return SWITCH_STATUS_SUCCESS;
275 }
276
skinny_api_cmd_profile_device_kill(const char * profile_name,const char * device_name,switch_stream_handle_t * stream)277 static switch_status_t skinny_api_cmd_profile_device_kill(const char *profile_name, const char *device_name, switch_stream_handle_t *stream)
278 {
279 skinny_profile_t *profile;
280
281 if ((profile = skinny_find_profile(profile_name))) {
282 listener_t *listener = NULL;
283 skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
284 if(listener) {
285 kill_listener(listener, NULL);
286 stream->write_function(stream, "+OK\n");
287 } else {
288 stream->write_function(stream, "Listener not found!\n");
289 }
290 } else {
291 stream->write_function(stream, "Profile not found!\n");
292 }
293
294 return SWITCH_STATUS_SUCCESS;
295 }
296
skinny_api_cmd_profile_kill_all(const char * profile_name,switch_stream_handle_t * stream)297 static switch_status_t skinny_api_cmd_profile_kill_all(const char *profile_name, switch_stream_handle_t *stream)
298 {
299 skinny_profile_t *profile;
300
301 if ((profile = skinny_find_profile(profile_name))) {
302 profile_walk_listeners(profile, kill_listener, NULL);
303 stream->write_function(stream, "+OK\n");
304 } else {
305 stream->write_function(stream, "Profile not found!\n");
306 }
307
308 return SWITCH_STATUS_SUCCESS;
309 }
310
skinny_api_cmd_profile_device_send_ringer_message(const char * profile_name,const char * device_name,const char * ring_type,const char * ring_mode,switch_stream_handle_t * stream)311 static switch_status_t skinny_api_cmd_profile_device_send_ringer_message(const char *profile_name, const char *device_name, const char *ring_type, const char *ring_mode, switch_stream_handle_t *stream)
312 {
313 skinny_profile_t *profile;
314
315 if ((profile = skinny_find_profile(profile_name))) {
316 listener_t *listener = NULL;
317 skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
318 if(listener) {
319 send_set_ringer(listener, skinny_str2ring_type(ring_type), skinny_str2ring_mode(ring_mode), 0, 0);
320 stream->write_function(stream, "+OK\n");
321 } else {
322 stream->write_function(stream, "Listener not found!\n");
323 }
324 } else {
325 stream->write_function(stream, "Profile not found!\n");
326 }
327
328 return SWITCH_STATUS_SUCCESS;
329 }
330
skinny_api_cmd_profile_device_send_lamp_message(const char * profile_name,const char * device_name,const char * stimulus,const char * instance,const char * lamp_mode,switch_stream_handle_t * stream)331 static switch_status_t skinny_api_cmd_profile_device_send_lamp_message(const char *profile_name, const char *device_name, const char *stimulus, const char *instance, const char *lamp_mode, switch_stream_handle_t *stream)
332 {
333 skinny_profile_t *profile;
334
335 if ((profile = skinny_find_profile(profile_name))) {
336 listener_t *listener = NULL;
337 skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
338 if(listener) {
339 send_set_lamp(listener, skinny_str2button(stimulus), atoi(instance), skinny_str2lamp_mode(lamp_mode));
340 stream->write_function(stream, "+OK\n");
341 } else {
342 stream->write_function(stream, "Listener not found!\n");
343 }
344 } else {
345 stream->write_function(stream, "Profile not found!\n");
346 }
347
348 return SWITCH_STATUS_SUCCESS;
349 }
350
skinny_api_cmd_profile_device_send_speaker_mode_message(const char * profile_name,const char * device_name,const char * speaker_mode,switch_stream_handle_t * stream)351 static switch_status_t skinny_api_cmd_profile_device_send_speaker_mode_message(const char *profile_name, const char *device_name, const char *speaker_mode, switch_stream_handle_t *stream)
352 {
353 skinny_profile_t *profile;
354
355 if ((profile = skinny_find_profile(profile_name))) {
356 listener_t *listener = NULL;
357 skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
358 if(listener) {
359 send_set_speaker_mode(listener, skinny_str2speaker_mode(speaker_mode));
360 stream->write_function(stream, "+OK\n");
361 } else {
362 stream->write_function(stream, "Listener not found!\n");
363 }
364 } else {
365 stream->write_function(stream, "Profile not found!\n");
366 }
367
368 return SWITCH_STATUS_SUCCESS;
369 }
370
skinny_api_cmd_profile_device_send_call_state_message(const char * profile_name,const char * device_name,const char * call_state,const char * line_instance,const char * call_id,switch_stream_handle_t * stream)371 static switch_status_t skinny_api_cmd_profile_device_send_call_state_message(const char *profile_name, const char *device_name, const char *call_state, const char *line_instance, const char *call_id, switch_stream_handle_t *stream)
372 {
373 skinny_profile_t *profile;
374
375 if ((profile = skinny_find_profile(profile_name))) {
376 listener_t *listener = NULL;
377 skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
378 if(listener) {
379 send_call_state(listener, skinny_str2call_state(call_state), atoi(line_instance), atoi(call_id));
380 stream->write_function(stream, "+OK\n");
381 } else {
382 stream->write_function(stream, "Listener not found!\n");
383 }
384 } else {
385 stream->write_function(stream, "Profile not found!\n");
386 }
387
388 return SWITCH_STATUS_SUCCESS;
389 }
390
skinny_api_cmd_profile_device_send_forward_stat_message(const char * profile_name,const char * device_name,const char * number,switch_stream_handle_t * stream)391 static switch_status_t skinny_api_cmd_profile_device_send_forward_stat_message(const char *profile_name, const char *device_name, const char *number, switch_stream_handle_t *stream)
392 {
393 skinny_profile_t *profile;
394
395 if ((profile = skinny_find_profile(profile_name))) {
396 listener_t *listener = NULL;
397 skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
398 if(listener) {
399
400 send_forward_stat(listener, number);
401
402 stream->write_function(stream, "+OK\n");
403 } else {
404 stream->write_function(stream, "Listener not found!\n");
405 }
406 } else {
407 stream->write_function(stream, "Profile not found!\n");
408 }
409
410 return SWITCH_STATUS_SUCCESS;
411 }
412
skinny_api_cmd_profile_device_send_display_prompt_status_message(const char * profile_name,const char * device_name,const char * display,switch_stream_handle_t * stream)413 static switch_status_t skinny_api_cmd_profile_device_send_display_prompt_status_message(const char *profile_name, const char *device_name, const char *display, switch_stream_handle_t *stream)
414 {
415 skinny_profile_t *profile;
416
417 if ((profile = skinny_find_profile(profile_name))) {
418 listener_t *listener = NULL;
419 skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
420 if(listener) {
421
422 send_display_prompt_status(listener, 0, display, 0, 0);
423
424 stream->write_function(stream, "+OK\n");
425 } else {
426 stream->write_function(stream, "Listener not found!\n");
427 }
428 } else {
429 stream->write_function(stream, "Profile not found!\n");
430 }
431
432 return SWITCH_STATUS_SUCCESS;
433 }
434
skinny_api_cmd_profile_device_send_reset_message(const char * profile_name,const char * device_name,const char * reset_type,switch_stream_handle_t * stream)435 static switch_status_t skinny_api_cmd_profile_device_send_reset_message(const char *profile_name, const char *device_name, const char *reset_type, switch_stream_handle_t *stream)
436 {
437 skinny_profile_t *profile;
438
439 if ((profile = skinny_find_profile(profile_name))) {
440 listener_t *listener = NULL;
441 skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
442 if(listener) {
443 send_reset(listener, skinny_str2device_reset_type(reset_type));
444 stream->write_function(stream, "+OK\n");
445 } else {
446 stream->write_function(stream, "Listener not found!\n");
447 }
448 } else {
449 stream->write_function(stream, "Profile not found!\n");
450 }
451
452 return SWITCH_STATUS_SUCCESS;
453 }
454
skinny_api_cmd_profile_device_send_data(const char * profile_name,const char * device_name,const char * message_type,char * params,const char * body,switch_stream_handle_t * stream)455 static switch_status_t skinny_api_cmd_profile_device_send_data(const char *profile_name, const char *device_name, const char *message_type, char *params, const char *body, switch_stream_handle_t *stream)
456 {
457 skinny_profile_t *profile;
458
459 if ((profile = skinny_find_profile(profile_name))) {
460 listener_t *listener = NULL;
461 skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
462 if(listener) {
463 switch_event_t *event = NULL;
464 char *argv[64] = { 0 };
465 int argc = 0;
466 int x = 0;
467 /* skinny::user_to_device event */
468 skinny_device_event(listener, &event, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_USER_TO_DEVICE);
469 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Message-Id-String", "%s", message_type);
470 argc = switch_separate_string(params, ';', argv, (sizeof(argv) / sizeof(argv[0])));
471 for (x = 0; x < argc; x++) {
472 char *var_name, *var_value = NULL;
473 var_name = argv[x];
474 if (var_name && (var_value = strchr(var_name, '='))) {
475 *var_value++ = '\0';
476 }
477 if (zstr(var_name)) {
478 stream->write_function(stream, "-ERR No variable specified\n");
479 } else {
480 char *tmp = switch_mprintf("Skinny-UserToDevice-%s", var_name);
481 switch_event_add_header(event, SWITCH_STACK_BOTTOM, tmp, "%s", var_value);
482 switch_safe_free(tmp);
483 /*
484 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Application-Id", "%d", request->data.extended_data.application_id);
485 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Line-Instance", "%d", request->data.extended_data.line_instance);
486 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Call-Id", "%d", request->data.extended_data.call_id);
487 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Transaction-Id", "%d", request->data.extended_data.transaction_id);
488 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Data-Length", "%d", request->data.extended_data.data_length);
489 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Sequence-Flag", "%d", request->data.extended_data.sequence_flag);
490 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Display-Priority", "%d", request->data.extended_data.display_priority);
491 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Conference-Id", "%d", request->data.extended_data.conference_id);
492 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-App-Instance-Id", "%d", request->data.extended_data.app_instance_id);
493 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Routing-Id", "%d", request->data.extended_data.routing_id);
494 */
495 }
496 }
497 switch_event_add_body(event, "%s", body);
498 switch_event_fire(&event);
499 stream->write_function(stream, "+OK\n");
500 } else {
501 stream->write_function(stream, "Listener not found!\n");
502 }
503 } else {
504 stream->write_function(stream, "Profile not found!\n");
505 }
506
507 return SWITCH_STATUS_SUCCESS;
508 }
509
510
skinny_api_cmd_profile_set(const char * profile_name,const char * name,const char * value,switch_stream_handle_t * stream)511 static switch_status_t skinny_api_cmd_profile_set(const char *profile_name, const char *name, const char *value, switch_stream_handle_t *stream)
512 {
513 skinny_profile_t *profile;
514
515 if ((profile = skinny_find_profile(profile_name))) {
516 if (skinny_profile_set(profile, name, value) == SWITCH_STATUS_SUCCESS) {
517 skinny_profile_respawn(profile, 0);
518 stream->write_function(stream, "+OK\n");
519 } else {
520 stream->write_function(stream, "Unable to set skinny setting '%s'. Does it exists?\n", name);
521 }
522 } else {
523 stream->write_function(stream, "Profile not found!\n");
524 }
525
526 return SWITCH_STATUS_SUCCESS;
527 }
528
529 /*****************************************************************************/
530 /* API */
531 /*****************************************************************************/
SWITCH_STANDARD_API(skinny_function)532 SWITCH_STANDARD_API(skinny_function)
533 {
534 char *argv[1024] = { 0 };
535 int argc = 0;
536 char *mycmd = NULL;
537 switch_status_t status = SWITCH_STATUS_SUCCESS;
538 const char *usage_string = "USAGE:\n"
539 "--------------------------------------------------------------------------------\n"
540 "skinny help\n"
541 "skinny status profile <profile_name>\n"
542 "skinny status profile <profile_name> device <device_name>\n"
543 "skinny profile <profile_name> device <device_name> send ResetMessage [DeviceReset|DeviceRestart]\n"
544 "skinny profile <profile_name> device <device_name> send SetRingerMessage <ring_type> <ring_mode>\n"
545 "skinny profile <profile_name> device <device_name> send SetLampMessage <stimulus> <instance> <lamp_mode>\n"
546 "skinny profile <profile_name> device <device_name> send SetSpeakerModeMessage <speaker_mode>\n"
547 "skinny profile <profile_name> device <device_name> send CallStateMessage <call_state> <line_instance> <call_id>\n"
548 "skinny profile <profile_name> device <device_name> send ForwardStatMessage <number>\n"
549 "skinny profile <profile_name> device <device_name> send DisplayPromptStatus <message>\n"
550 "skinny profile <profile_name> device <device_name> send <UserToDeviceDataMessage|UserToDeviceDataVersion1Message> [ <param>=<value>;... ] <data>\n"
551 "skinny profile <profile_name> set <name> <value>\n"
552 "--------------------------------------------------------------------------------\n";
553 if (session) {
554 return SWITCH_STATUS_FALSE;
555 }
556
557 if (zstr(cmd)) {
558 stream->write_function(stream, "%s", usage_string);
559 goto done;
560 }
561
562 if (!(mycmd = strdup(cmd))) {
563 status = SWITCH_STATUS_MEMERR;
564 goto done;
565 }
566
567 if (!(argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) || !argv[0]) {
568 stream->write_function(stream, "%s", usage_string);
569 goto done;
570 }
571
572 if (!strcasecmp(argv[0], "help")) {/* skinny help */
573 stream->write_function(stream, "%s", usage_string);
574 } else if (argc == 3 && !strcasecmp(argv[0], "status") && !strcasecmp(argv[1], "profile")) {
575 /* skinny status profile <profile_name> */
576 status = skinny_api_cmd_status_profile(argv[2], stream);
577 } else if (argc == 3 && !strcasecmp(argv[0], "profile") && !strcasecmp(argv[2], "kill_all")) {
578 /* skinny profile <profile_name> kill_all */
579 status = skinny_api_cmd_profile_kill_all(argv[1],stream);
580 } else if (argc == 5 && !strcasecmp(argv[0], "status") && !strcasecmp(argv[1], "profile") && !strcasecmp(argv[3], "device")) {
581 /* skinny status profile <profile_name> device <device_name> */
582 status = skinny_api_cmd_status_profile_device(argv[2], argv[4], stream);
583 } else if (argc == 5 && !strcasecmp(argv[0], "profile") && !strcasecmp(argv[2], "device") && !strcasecmp(argv[4], "kill")) {
584 /* skinny profile <profile_name> device <device_name> kill */
585 status = skinny_api_cmd_profile_device_kill(argv[1],argv[3],stream);
586 } else if (argc >= 6 && !strcasecmp(argv[0], "profile") && !strcasecmp(argv[2], "device") && !strcasecmp(argv[4], "send")) {
587 /* skinny profile <profile_name> device <device_name> send ... */
588 switch(skinny_str2message_type(argv[5])) {
589 case SET_RINGER_MESSAGE:
590 if(argc == 8) {
591 /* SetRingerMessage <ring_type> <ring_mode> */
592 status = skinny_api_cmd_profile_device_send_ringer_message(argv[1], argv[3], argv[6], argv[7], stream);
593 }
594 break;
595 case SET_LAMP_MESSAGE:
596 if (argc == 9) {
597 /* SetLampMessage <stimulus> <instance> <lamp_mode> */
598 status = skinny_api_cmd_profile_device_send_lamp_message(argv[1], argv[3], argv[6], argv[7], argv[8], stream);
599 }
600 break;
601 case SET_SPEAKER_MODE_MESSAGE:
602 if (argc == 7) {
603 /* SetSpeakerModeMessage <speaker_mode> */
604 status = skinny_api_cmd_profile_device_send_speaker_mode_message(argv[1], argv[3], argv[6], stream);
605 }
606 break;
607 case CALL_STATE_MESSAGE:
608 if (argc == 9) {
609 /* CallStateMessage <call_state> <line_instance> <call_id> */
610 status = skinny_api_cmd_profile_device_send_call_state_message(argv[1], argv[3], argv[6], argv[7], argv[8], stream);
611 }
612 break;
613 case FORWARD_STAT_MESSAGE:
614 if (argc == 7) {
615 /* ForwardStatMessage <number> */
616 status = skinny_api_cmd_profile_device_send_forward_stat_message(argv[1], argv[3], argv[6], stream);
617 } else if (argc == 6) {
618 /* ForwardStatMessage */
619 status = skinny_api_cmd_profile_device_send_forward_stat_message(argv[1], argv[3], NULL, stream);
620 }
621 break;
622 case DISPLAY_PROMPT_STATUS_MESSAGE:
623 if (argc == 7) {
624 /* DisplayPromptStatus <display> */
625 status = skinny_api_cmd_profile_device_send_display_prompt_status_message(argv[1], argv[3], argv[6], stream);
626 }
627 break;
628 case RESET_MESSAGE:
629 if (argc == 7) {
630 /* ResetMessage <reset_type> */
631 status = skinny_api_cmd_profile_device_send_reset_message(argv[1], argv[3], argv[6], stream);
632 }
633 break;
634 case USER_TO_DEVICE_DATA_MESSAGE:
635 case USER_TO_DEVICE_DATA_VERSION1_MESSAGE:
636 if(argc == 8) {
637 /* <UserToDeviceDataMessage|UserToDeviceDataVersion1Message> [ <param>=<value>;... ] <data> */
638 status = skinny_api_cmd_profile_device_send_data(argv[1], argv[3], argv[5], argv[6], argv[7], stream);
639 } else if(argc == 7) {
640 /* <UserToDeviceDataMessage|UserToDeviceDataVersion1Message> <data> */
641 status = skinny_api_cmd_profile_device_send_data(argv[1], argv[3], argv[5], "", argv[6], stream);
642 }
643 break;
644 default:
645 stream->write_function(stream, "Unhandled message %s\n", argv[5]);
646 }
647 } else if (argc == 5 && !strcasecmp(argv[0], "profile") && !strcasecmp(argv[2], "set")) {
648 /* skinny profile <profile_name> set <name> <value> */
649 status = skinny_api_cmd_profile_set(argv[1], argv[3], argv[4], stream);
650 } else {
651 stream->write_function(stream, "%s", usage_string);
652 }
653
654 done:
655 switch_safe_free(mycmd);
656 return status;
657 }
658
skinny_api_register(switch_loadable_module_interface_t ** module_interface)659 switch_status_t skinny_api_register(switch_loadable_module_interface_t **module_interface)
660 {
661 switch_api_interface_t *api_interface;
662
663 SWITCH_ADD_API(api_interface, "skinny", "Skinny Controls", skinny_function, "<cmd> <args>");
664 switch_console_set_complete("add skinny help");
665
666 switch_console_set_complete("add skinny status profile ::skinny::list_profiles");
667 switch_console_set_complete("add skinny status profile ::skinny::list_profiles device ::skinny::list_devices");
668
669 switch_console_set_complete("add skinny profile ::skinny::list_profiles kill_all");
670
671 switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices kill");
672
673 switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send ResetMessage ::skinny::list_reset_types");
674 switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send SetRingerMessage ::skinny::list_ring_types ::skinny::list_ring_modes");
675 switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send SetLampMessage ::skinny::list_stimuli ::skinny::list_stimulus_instances ::skinny::list_stimulus_modes");
676 switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send SetSpeakerModeMessage ::skinny::list_speaker_modes");
677 switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send CallStateMessage ::skinny::list_call_states ::skinny::list_line_instances ::skinny::list_call_ids");
678 switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send ForwardStatMessage");
679 switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send DisplayPromptStatusMessage");
680 switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send UserToDeviceDataMessage");
681 switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send UserToDeviceDataVersion1Message");
682 switch_console_set_complete("add skinny profile ::skinny::list_profiles set ::skinny::list_settings");
683
684 switch_console_add_complete_func("::skinny::list_profiles", skinny_api_list_profiles);
685 switch_console_add_complete_func("::skinny::list_devices", skinny_api_list_devices);
686 switch_console_add_complete_func("::skinny::list_reset_types", skinny_api_list_reset_types);
687 switch_console_add_complete_func("::skinny::list_ring_types", skinny_api_list_ring_types);
688 switch_console_add_complete_func("::skinny::list_ring_modes", skinny_api_list_ring_modes);
689 switch_console_add_complete_func("::skinny::list_stimuli", skinny_api_list_stimuli);
690 switch_console_add_complete_func("::skinny::list_stimulus_instances", skinny_api_list_stimulus_instances);
691 switch_console_add_complete_func("::skinny::list_stimulus_modes", skinny_api_list_stimulus_modes);
692 switch_console_add_complete_func("::skinny::list_speaker_modes", skinny_api_list_speaker_modes);
693 switch_console_add_complete_func("::skinny::list_call_states", skinny_api_list_call_states);
694 switch_console_add_complete_func("::skinny::list_line_instances", skinny_api_list_line_instances);
695 switch_console_add_complete_func("::skinny::list_call_ids", skinny_api_list_call_ids);
696 switch_console_add_complete_func("::skinny::list_settings", skinny_api_list_settings);
697 return SWITCH_STATUS_SUCCESS;
698 }
699
skinny_api_unregister()700 switch_status_t skinny_api_unregister()
701 {
702 switch_console_set_complete("del skinny");
703
704 return SWITCH_STATUS_SUCCESS;
705 }
706
707 /* For Emacs:
708 * Local Variables:
709 * mode:c
710 * indent-tabs-mode:t
711 * tab-width:4
712 * c-basic-offset:4
713 * End:
714 * For VIM:
715 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
716 */
717
718