Bug Summary

File:src/mod/endpoints/mod_skinny/mod_skinny.c
Location:line 2311, column 13
Description:Value stored to 'data_length' during its initialization is never read

Annotated Source Code

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 * mod_skinny.c -- Skinny Call Control Protocol (SCCP) Endpoint Module
30 *
31 */
32#include <switch.h>
33#include "mod_skinny.h"
34#include "skinny_protocol.h"
35#include "skinny_server.h"
36#include "skinny_tables.h"
37#include "skinny_api.h"
38
39SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load)switch_status_t mod_skinny_load (switch_loadable_module_interface_t
**module_interface, switch_memory_pool_t *pool)
;
40SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skinny_shutdown)switch_status_t mod_skinny_shutdown (void);
41
42SWITCH_MODULE_DEFINITION(mod_skinny, mod_skinny_load, mod_skinny_shutdown, NULL)static const char modname[] = "mod_skinny" ; __attribute__((visibility
("default"))) switch_loadable_module_function_table_t mod_skinny_module_interface
= { 5, mod_skinny_load, mod_skinny_shutdown, ((void*)0), SMODF_NONE
}
;
43
44switch_endpoint_interface_t *skinny_endpoint_interface;
45
46skinny_globals_t globals;
47
48/*****************************************************************************/
49/* SQL TABLES */
50/*****************************************************************************/
51static char devices_sql[] =
52"CREATE TABLE skinny_devices (\n"
53" name VARCHAR(16),\n"
54" user_id INTEGER,\n"
55" instance INTEGER,\n"
56" ip VARCHAR(15),\n"
57" type INTEGER,\n"
58" max_streams INTEGER,\n"
59" port INTEGER,\n"
60" codec_string VARCHAR(255),\n"
61" headset INTEGER,\n"
62" handset INTEGER,\n"
63" speaker INTEGER\n"
64");\n";
65
66static char lines_sql[] =
67"CREATE TABLE skinny_lines (\n"
68" device_name VARCHAR(16),\n"
69" device_instance INTEGER,\n"
70" position INTEGER,\n"
71" line_instance INTEGER,\n"
72" label VARCHAR(40),\n"
73" value VARCHAR(24),\n"
74" caller_name VARCHAR(44),\n"
75" ring_on_idle INTEGER,\n"
76" ring_on_active INTEGER,\n"
77" busy_trigger INTEGER,\n"
78" forward_all VARCHAR(255),\n"
79" forward_busy VARCHAR(255),\n"
80" forward_noanswer VARCHAR(255),\n"
81" noanswer_duration INTEGER\n"
82");\n";
83
84static char buttons_sql[] =
85"CREATE TABLE skinny_buttons (\n"
86" device_name VARCHAR(16),\n"
87" device_instance INTEGER,\n"
88" position INTEGER,\n"
89" type INTEGER,\n"
90" label VARCHAR(40),\n"
91" value VARCHAR(255),\n"
92" settings VARCHAR(44)\n"
93");\n";
94
95static char active_lines_sql[] =
96"CREATE TABLE skinny_active_lines (\n"
97" device_name VARCHAR(16),\n"
98" device_instance INTEGER,\n"
99" line_instance INTEGER,\n"
100" channel_uuid VARCHAR(256),\n"
101" call_id INTEGER,\n"
102" call_state INTEGER\n"
103");\n";
104
105/*****************************************************************************/
106/* TEXT FUNCTIONS */
107/*****************************************************************************/
108char *skinny_format_message(const char *str)
109{
110 char *tmp;
111 switch_size_t i;
112
113 /* Look for \200, if found, next character indicates string id */
114 char match = (char) 128;
115
116 tmp = switch_mprintf("");
117
118 if (zstr(str)_zstr(str)) {
119 return tmp;
120 }
121
122 for (i=0; i<strlen(str); i++)
123 {
124 char *old = tmp;
125
126 if ( str[i] == match ) {
127 if ( tmp[0] ) {
128 tmp = switch_mprintf("%s [%s] ", old, skinny_textid2str(str[i+1]));
129 } else {
130 tmp = switch_mprintf("[%s] ", skinny_textid2str(str[i+1]));
131 }
132 switch_safe_free(old)if (old) {free(old);old=((void*)0);};
133 i++;
134 } else if ( !switch_isprint(str[i]) ) {
135 tmp = switch_mprintf("%s\\x%.2X", old, str[i]);
136 switch_safe_free(old)if (old) {free(old);old=((void*)0);};
137 } else {
138 tmp = switch_mprintf("%s%c", old, str[i]);
139 switch_safe_free(old)if (old) {free(old);old=((void*)0);};
140 }
141 }
142
143 return tmp;
144}
145
146/*****************************************************************************/
147/* PROFILES FUNCTIONS */
148/*****************************************************************************/
149switch_status_t skinny_profile_dump(const skinny_profile_t *profile, switch_stream_handle_t *stream)
150{
151 const char *line = "=================================================================================================";
152 switch_assert(profile)((profile) ? (void) (0) : __assert_fail ("profile", "mod_skinny.c"
, 152, __PRETTY_FUNCTION__))
;
153 stream->write_function(stream, "%s\n", line);
154 /* prefs */
155 stream->write_function(stream, "Name \t%s\n", profile->name);
156 stream->write_function(stream, "Domain Name \t%s\n", profile->domain);
157 stream->write_function(stream, "IP \t%s\n", profile->ip);
158 stream->write_function(stream, "Port \t%d\n", profile->port);
159 stream->write_function(stream, "Dialplan \t%s\n", profile->dialplan);
160 stream->write_function(stream, "Context \t%s\n", profile->context);
161 stream->write_function(stream, "Patterns-Dialplan \t%s\n", profile->patterns_dialplan);
162 stream->write_function(stream, "Patterns-Context \t%s\n", profile->patterns_context);
163 stream->write_function(stream, "Keep-Alive \t%d\n", profile->keep_alive);
164 stream->write_function(stream, "Digit-Timeout \t%d\n", profile->digit_timeout);
165 stream->write_function(stream, "Date-Format \t%s\n", profile->date_format);
166 stream->write_function(stream, "DBName \t%s\n", profile->dbname ? profile->dbname : switch_str_nil(profile->odbc_dsn)(profile->odbc_dsn ? profile->odbc_dsn : ""));
167 stream->write_function(stream, "Debug \t%d\n", profile->debug);
168 stream->write_function(stream, "Auto-Restart \t%d\n", profile->auto_restart);
169 stream->write_function(stream, "Non-Blocking \t%d\n", profile->non_blocking);
170 /* stats */
171 stream->write_function(stream, "CALLS-IN \t%d\n", profile->ib_calls);
172 stream->write_function(stream, "FAILED-CALLS-IN \t%d\n", profile->ib_failed_calls);
173 stream->write_function(stream, "CALLS-OUT \t%d\n", profile->ob_calls);
174 stream->write_function(stream, "FAILED-CALLS-OUT \t%d\n", profile->ob_failed_calls);
175 /* listener */
176 stream->write_function(stream, "Listener-Threads \t%d\n", profile->listener_threads);
177 stream->write_function(stream, "Ext-Voicemail \t%s\n", profile->ext_voicemail);
178 stream->write_function(stream, "Ext-Redial \t%s\n", profile->ext_redial);
179 stream->write_function(stream, "Ext-MeetMe \t%s\n", profile->ext_meetme);
180 stream->write_function(stream, "Ext-PickUp \t%s\n", profile->ext_pickup);
181 stream->write_function(stream, "Ext-CFwdAll \t%s\n", profile->ext_cfwdall);
182 stream->write_function(stream, "%s\n", line);
183
184 return SWITCH_STATUS_SUCCESS;
185}
186
187
188skinny_profile_t *skinny_find_profile(const char *profile_name)
189{
190 skinny_profile_t *profile;
191 switch_mutex_lock(globals.mutex);
192 profile = (skinny_profile_t *) switch_core_hash_find(globals.profile_hash, profile_name);
193 switch_mutex_unlock(globals.mutex);
194 return profile;
195}
196
197skinny_profile_t *skinny_find_profile_by_domain(const char *domain_name)
198{
199
200 switch_hash_index_t *hi;
201 void *val;
202 skinny_profile_t *profile = NULL((void*)0), *tmp_profile;
203
204 switch_mutex_lock(globals.mutex);
205 for (hi = switch_core_hash_first(globals.profile_hash)switch_core_hash_first_iter(globals.profile_hash, ((void*)0)); hi; hi = switch_core_hash_next(&hi)) {
206 switch_core_hash_this(hi, NULL((void*)0), NULL((void*)0), &val);
207 tmp_profile = (skinny_profile_t *) val;
208
209 switch_mutex_lock(tmp_profile->listener_mutex);
210 if (!strcmp(tmp_profile->domain, domain_name)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(tmp_profile->domain) && __builtin_constant_p (domain_name
) && (__s1_len = __builtin_strlen (tmp_profile->domain
), __s2_len = __builtin_strlen (domain_name), (!((size_t)(const
void *)((tmp_profile->domain) + 1) - (size_t)(const void *
)(tmp_profile->domain) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((domain_name) + 1) - (size_t)(const
void *)(domain_name) == 1) || __s2_len >= 4)) ? __builtin_strcmp
(tmp_profile->domain, domain_name) : (__builtin_constant_p
(tmp_profile->domain) && ((size_t)(const void *)(
(tmp_profile->domain) + 1) - (size_t)(const void *)(tmp_profile
->domain) == 1) && (__s1_len = __builtin_strlen (tmp_profile
->domain), __s1_len < 4) ? (__builtin_constant_p (domain_name
) && ((size_t)(const void *)((domain_name) + 1) - (size_t
)(const void *)(domain_name) == 1) ? __builtin_strcmp (tmp_profile
->domain, domain_name) : (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (domain_name)
; int __result = (((const unsigned char *) (const char *) (tmp_profile
->domain))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
tmp_profile->domain))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (tmp_profile->domain))[2] - __s2[2]); if (__s1_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (tmp_profile->domain))[3] - __s2[3
]); } } __result; }))) : (__builtin_constant_p (domain_name) &&
((size_t)(const void *)((domain_name) + 1) - (size_t)(const void
*)(domain_name) == 1) && (__s2_len = __builtin_strlen
(domain_name), __s2_len < 4) ? (__builtin_constant_p (tmp_profile
->domain) && ((size_t)(const void *)((tmp_profile->
domain) + 1) - (size_t)(const void *)(tmp_profile->domain)
== 1) ? __builtin_strcmp (tmp_profile->domain, domain_name
) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (tmp_profile->domain); int __result
= (((const unsigned char *) (const char *) (domain_name))[0]
- __s2[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (domain_name))[1]
- __s2[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (domain_name))[2]
- __s2[2]); if (__s2_len > 2 && __result == 0) __result
= (((const unsigned char *) (const char *) (domain_name))[3]
- __s2[3]); } } __result; })))) : __builtin_strcmp (tmp_profile
->domain, domain_name)))); })
) {
211 profile = tmp_profile;
212 }
213 switch_mutex_unlock(tmp_profile->listener_mutex);
214 if (profile) {
215 break;
216 }
217 }
218 switch_safe_free(hi)if (hi) {free(hi);hi=((void*)0);};
219 switch_mutex_unlock(globals.mutex);
220
221 return profile;
222}
223
224switch_status_t skinny_profile_find_listener_by_device_name(skinny_profile_t *profile, const char *device_name, listener_t **listener)
225{
226 listener_t *l;
227
228 switch_mutex_lock(profile->listener_mutex);
229 for (l = profile->listeners; l; l = l->next) {
230 if (!strcmp(l->device_name, device_name)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(l->device_name) && __builtin_constant_p (device_name
) && (__s1_len = __builtin_strlen (l->device_name)
, __s2_len = __builtin_strlen (device_name), (!((size_t)(const
void *)((l->device_name) + 1) - (size_t)(const void *)(l->
device_name) == 1) || __s1_len >= 4) && (!((size_t
)(const void *)((device_name) + 1) - (size_t)(const void *)(device_name
) == 1) || __s2_len >= 4)) ? __builtin_strcmp (l->device_name
, device_name) : (__builtin_constant_p (l->device_name) &&
((size_t)(const void *)((l->device_name) + 1) - (size_t)(
const void *)(l->device_name) == 1) && (__s1_len =
__builtin_strlen (l->device_name), __s1_len < 4) ? (__builtin_constant_p
(device_name) && ((size_t)(const void *)((device_name
) + 1) - (size_t)(const void *)(device_name) == 1) ? __builtin_strcmp
(l->device_name, device_name) : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (device_name
); int __result = (((const unsigned char *) (const char *) (l
->device_name))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (l->device_name))[1] - __s2[1]); if (__s1_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (l->device_name))[2] - __s2[2]); if (__s1_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (l->device_name))[3] - __s2[3]); }
} __result; }))) : (__builtin_constant_p (device_name) &&
((size_t)(const void *)((device_name) + 1) - (size_t)(const void
*)(device_name) == 1) && (__s2_len = __builtin_strlen
(device_name), __s2_len < 4) ? (__builtin_constant_p (l->
device_name) && ((size_t)(const void *)((l->device_name
) + 1) - (size_t)(const void *)(l->device_name) == 1) ? __builtin_strcmp
(l->device_name, device_name) : (- (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
(l->device_name); int __result = (((const unsigned char *
) (const char *) (device_name))[0] - __s2[0]); if (__s2_len >
0 && __result == 0) { __result = (((const unsigned char
*) (const char *) (device_name))[1] - __s2[1]); if (__s2_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) (device_name))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (device_name))[3] - __s2[3]); } } __result
; })))) : __builtin_strcmp (l->device_name, device_name)))
); })
) {
231 *listener = l;
232 }
233 }
234 switch_mutex_unlock(profile->listener_mutex);
235
236 return SWITCH_STATUS_SUCCESS;
237}
238
239switch_status_t skinny_profile_find_listener_by_device_name_and_instance(skinny_profile_t *profile, const char *device_name, uint32_t device_instance, listener_t **listener)
240{
241 listener_t *l;
242
243 switch_mutex_lock(profile->listener_mutex);
244 for (l = profile->listeners; l; l = l->next) {
245 if (!strcmp(l->device_name, device_name)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(l->device_name) && __builtin_constant_p (device_name
) && (__s1_len = __builtin_strlen (l->device_name)
, __s2_len = __builtin_strlen (device_name), (!((size_t)(const
void *)((l->device_name) + 1) - (size_t)(const void *)(l->
device_name) == 1) || __s1_len >= 4) && (!((size_t
)(const void *)((device_name) + 1) - (size_t)(const void *)(device_name
) == 1) || __s2_len >= 4)) ? __builtin_strcmp (l->device_name
, device_name) : (__builtin_constant_p (l->device_name) &&
((size_t)(const void *)((l->device_name) + 1) - (size_t)(
const void *)(l->device_name) == 1) && (__s1_len =
__builtin_strlen (l->device_name), __s1_len < 4) ? (__builtin_constant_p
(device_name) && ((size_t)(const void *)((device_name
) + 1) - (size_t)(const void *)(device_name) == 1) ? __builtin_strcmp
(l->device_name, device_name) : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (device_name
); int __result = (((const unsigned char *) (const char *) (l
->device_name))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (l->device_name))[1] - __s2[1]); if (__s1_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (l->device_name))[2] - __s2[2]); if (__s1_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (l->device_name))[3] - __s2[3]); }
} __result; }))) : (__builtin_constant_p (device_name) &&
((size_t)(const void *)((device_name) + 1) - (size_t)(const void
*)(device_name) == 1) && (__s2_len = __builtin_strlen
(device_name), __s2_len < 4) ? (__builtin_constant_p (l->
device_name) && ((size_t)(const void *)((l->device_name
) + 1) - (size_t)(const void *)(l->device_name) == 1) ? __builtin_strcmp
(l->device_name, device_name) : (- (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
(l->device_name); int __result = (((const unsigned char *
) (const char *) (device_name))[0] - __s2[0]); if (__s2_len >
0 && __result == 0) { __result = (((const unsigned char
*) (const char *) (device_name))[1] - __s2[1]); if (__s2_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) (device_name))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (device_name))[3] - __s2[3]); } } __result
; })))) : __builtin_strcmp (l->device_name, device_name)))
); })
&& (l->device_instance == device_instance)) {
246 *listener = l;
247 }
248 }
249 switch_mutex_unlock(profile->listener_mutex);
250
251 return SWITCH_STATUS_SUCCESS;
252}
253
254struct skinny_profile_find_session_uuid_helper {
255 skinny_profile_t *profile;
256 char *channel_uuid;
257 uint32_t line_instance;
258};
259
260int skinny_profile_find_session_uuid_callback(void *pArg, int argc, char **argv, char **columnNames)
261{
262 struct skinny_profile_find_session_uuid_helper *helper = pArg;
263
264 char *channel_uuid = argv[0];
265 uint32_t line_instance = atoi(argv[1]);
266
267 if(helper->channel_uuid == NULL((void*)0)) {
268 helper->channel_uuid = switch_mprintf("%s", channel_uuid);
269 helper->line_instance = line_instance;
270 }
271
272 return 0;
273}
274
275char * skinny_profile_find_session_uuid(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id)
276{
277 struct skinny_profile_find_session_uuid_helper helper = {0};
278 char *sql;
279 char *device_condition = NULL((void*)0);
280 char *line_instance_condition = NULL((void*)0);
281 char *call_id_condition = NULL((void*)0);
282
283 switch_assert(profile)((profile) ? (void) (0) : __assert_fail ("profile", "mod_skinny.c"
, 283, __PRETTY_FUNCTION__))
;
284 helper.profile = profile;
285 helper.channel_uuid = NULL((void*)0);
286
287 if(listener) {
288 device_condition = switch_mprintf("device_name='%s' AND device_instance=%d",
289 listener->device_name, listener->device_instance);
290 } else {
291 device_condition = switch_mprintf("1=1");
292 }
293 switch_assert(device_condition)((device_condition) ? (void) (0) : __assert_fail ("device_condition"
, "mod_skinny.c", 293, __PRETTY_FUNCTION__))
;
294 if(*line_instance_p > 0) {
295 line_instance_condition = switch_mprintf("line_instance=%d", *line_instance_p);
296 } else {
297 line_instance_condition = switch_mprintf("1=1");
298 }
299 switch_assert(line_instance_condition)((line_instance_condition) ? (void) (0) : __assert_fail ("line_instance_condition"
, "mod_skinny.c", 299, __PRETTY_FUNCTION__))
;
300 if(call_id > 0) {
301 call_id_condition = switch_mprintf("call_id=%d", call_id);
302 } else {
303 call_id_condition = switch_mprintf("1=1");
304 }
305 switch_assert(call_id_condition)((call_id_condition) ? (void) (0) : __assert_fail ("call_id_condition"
, "mod_skinny.c", 305, __PRETTY_FUNCTION__))
;
306 if((sql = switch_mprintf(
307 "SELECT channel_uuid, line_instance "
308 "FROM skinny_active_lines "
309 "WHERE %s AND %s AND %s "
310 "ORDER BY call_state, channel_uuid", /* off hook first */
311 device_condition, line_instance_condition, call_id_condition
312 ))) {
313 skinny_execute_sql_callback(profile, profile->sql_mutex, sql,
314 skinny_profile_find_session_uuid_callback, &helper);
315 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
316 }
317 switch_safe_free(device_condition)if (device_condition) {free(device_condition);device_condition
=((void*)0);}
;
318 switch_safe_free(line_instance_condition)if (line_instance_condition) {free(line_instance_condition);line_instance_condition
=((void*)0);}
;
319 switch_safe_free(call_id_condition)if (call_id_condition) {free(call_id_condition);call_id_condition
=((void*)0);}
;
320 *line_instance_p = helper.line_instance;
321 return helper.channel_uuid;
322}
323
324#ifdef SWITCH_DEBUG_RWLOCKS
325switch_core_session_t * skinny_profile_perform_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id, const char *file, const char *func, int line)
326#else
327switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id)
328#endif
329{
330 char *uuid;
331 switch_core_session_t *result = NULL((void*)0);
332 uuid = skinny_profile_find_session_uuid(profile, listener, line_instance_p, call_id);
333
334 if(!zstr(uuid)_zstr(uuid)) {
335#ifdef SWITCH_DEBUG_RWLOCKS
336 result = switch_core_session_perform_locate(uuid, file, func, line);
337#else
338 result = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "mod_skinny.c", (const
char *)__func__, 338)
;
339#endif
340 if(!result) {
341 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 341, ((void*)0)
, SWITCH_LOG_WARNING,
342 "Unable to find session %s on %s:%d, line %d\n",
343 uuid, listener->device_name, listener->device_instance, *line_instance_p);
344 }
345 switch_safe_free(uuid)if (uuid) {free(uuid);uuid=((void*)0);};
346 }
347 return result;
348}
349
350/*****************************************************************************/
351/* SQL FUNCTIONS */
352/*****************************************************************************/
353switch_cache_db_handle_t *skinny_get_db_handle(skinny_profile_t *profile)
354{
355 switch_cache_db_handle_t *dbh = NULL((void*)0);
356 char *dsn;
357
358 if (!zstr(profile->odbc_dsn)_zstr(profile->odbc_dsn)) {
359 dsn = profile->odbc_dsn;
360 } else {
361 dsn = profile->dbname;
362 }
363
364 if (switch_cache_db_get_db_handle_dsn(&dbh, dsn)_switch_cache_db_get_db_handle_dsn(&dbh, dsn, "mod_skinny.c"
, (const char *)__func__, 364)
!= SWITCH_STATUS_SUCCESS) {
365 dbh = NULL((void*)0);
366 }
367
368 return dbh;
369
370}
371
372
373switch_status_t skinny_execute_sql(skinny_profile_t *profile, char *sql, switch_mutex_t *mutex)
374{
375 switch_cache_db_handle_t *dbh = NULL((void*)0);
376 switch_status_t status = SWITCH_STATUS_FALSE;
377
378 if (mutex) {
379 switch_mutex_lock(mutex);
380 }
381
382 if (!(dbh = skinny_get_db_handle(profile))) {
383 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 383, ((void*)0)
, SWITCH_LOG_ERROR, "Error Opening DB\n");
384 goto end;
385 }
386
387 status = switch_cache_db_execute_sql(dbh, sql, NULL((void*)0));
388
389end:
390
391 switch_cache_db_release_db_handle(&dbh);
392
393 if (mutex) {
394 switch_mutex_unlock(mutex);
395 }
396
397 return status;
398}
399
400switch_bool_t skinny_execute_sql_callback(skinny_profile_t *profile, switch_mutex_t *mutex, char *sql, switch_core_db_callback_func_t callback,
401 void *pdata)
402{
403 switch_bool_t ret = SWITCH_FALSE;
404 char *errmsg = NULL((void*)0);
405 switch_cache_db_handle_t *dbh = NULL((void*)0);
406
407 if (mutex) {
408 switch_mutex_lock(mutex);
409 }
410
411 if (!(dbh = skinny_get_db_handle(profile))) {
412 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 412, ((void*)0)
, SWITCH_LOG_ERROR, "Error Opening DB\n");
413 goto end;
414 }
415
416 switch_cache_db_execute_sql_callback(dbh, sql, callback, pdata, &errmsg);
417
418 if (errmsg) {
419 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 419, ((void*)0)
, SWITCH_LOG_ERROR, "SQL ERR: [%s] %s\n", sql, errmsg);
420 free(errmsg);
421 }
422
423end:
424
425 switch_cache_db_release_db_handle(&dbh);
426
427 if (mutex) {
428 switch_mutex_unlock(mutex);
429 }
430
431 return ret;
432}
433
434/*****************************************************************************/
435/* CHANNEL FUNCTIONS */
436/*****************************************************************************/
437void skinny_line_perform_set_state(const char *file, const char *func, int line, listener_t *listener, uint32_t line_instance, uint32_t call_id, uint32_t call_state)
438{
439 switch_event_t *event = NULL((void*)0);
440 switch_assert(listener)((listener) ? (void) (0) : __assert_fail ("listener", "mod_skinny.c"
, 440, __PRETTY_FUNCTION__))
;
441
442 skinny_device_event(listener, &event, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_CALL_STATE"skinny::call_state");
443 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-Line-Instance", "%d", line_instance);
444 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-Call-Id", "%d", call_id);
445 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-Call-State", "%d", call_state);
446 switch_event_fire(&event)switch_event_fire_detailed("mod_skinny.c", (const char * )(const
char *)__func__, 446, &event, ((void*)0))
;
447 send_call_state(listener, call_state, line_instance, call_id)perform_send_call_state(listener, "mod_skinny.c", (const char
*)__func__, 447, call_state, line_instance, call_id)
;
448
449 skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,switch_log_printf( SWITCH_CHANNEL_ID_LOG, file, func, line, (
(void*)0), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] " "Line %d, Call %d Change State to %s (%d)\n"
, (_zstr(listener->device_name) ? "_undef_" : listener->
device_name), listener->device_instance, (_zstr(listener->
remote_ip) ? "_undef_" : listener->remote_ip), listener->
remote_port, line_instance, call_id, skinny_call_state2str(call_state
), call_state)
450 "Line %d, Call %d Change State to %s (%d)\n",switch_log_printf( SWITCH_CHANNEL_ID_LOG, file, func, line, (
(void*)0), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] " "Line %d, Call %d Change State to %s (%d)\n"
, (_zstr(listener->device_name) ? "_undef_" : listener->
device_name), listener->device_instance, (_zstr(listener->
remote_ip) ? "_undef_" : listener->remote_ip), listener->
remote_port, line_instance, call_id, skinny_call_state2str(call_state
), call_state)
451 line_instance, call_id,switch_log_printf( SWITCH_CHANNEL_ID_LOG, file, func, line, (
(void*)0), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] " "Line %d, Call %d Change State to %s (%d)\n"
, (_zstr(listener->device_name) ? "_undef_" : listener->
device_name), listener->device_instance, (_zstr(listener->
remote_ip) ? "_undef_" : listener->remote_ip), listener->
remote_port, line_instance, call_id, skinny_call_state2str(call_state
), call_state)
452 skinny_call_state2str(call_state), call_state)switch_log_printf( SWITCH_CHANNEL_ID_LOG, file, func, line, (
(void*)0), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] " "Line %d, Call %d Change State to %s (%d)\n"
, (_zstr(listener->device_name) ? "_undef_" : listener->
device_name), listener->device_instance, (_zstr(listener->
remote_ip) ? "_undef_" : listener->remote_ip), listener->
remote_port, line_instance, call_id, skinny_call_state2str(call_state
), call_state)
;
453}
454
455
456struct skinny_line_get_state_helper {
457 uint32_t call_state;
458};
459
460int skinny_line_get_state_callback(void *pArg, int argc, char **argv, char **columnNames)
461{
462 struct skinny_line_get_state_helper *helper = pArg;
463 if (helper->call_state == -1) {
464 helper->call_state = atoi(argv[0]);
465 }
466 return 0;
467}
468
469uint32_t skinny_line_get_state(listener_t *listener, uint32_t line_instance, uint32_t call_id)
470{
471 char *line_instance_condition;
472 char *call_id_condition;
473 char *sql;
474 struct skinny_line_get_state_helper helper = {0};
475
476 switch_assert(listener)((listener) ? (void) (0) : __assert_fail ("listener", "mod_skinny.c"
, 476, __PRETTY_FUNCTION__))
;
477
478 if(line_instance > 0) {
479 line_instance_condition = switch_mprintf("line_instance=%d", line_instance);
480 } else {
481 line_instance_condition = switch_mprintf("1=1");
482 }
483 switch_assert(line_instance_condition)((line_instance_condition) ? (void) (0) : __assert_fail ("line_instance_condition"
, "mod_skinny.c", 483, __PRETTY_FUNCTION__))
;
484 if(call_id > 0) {
485 call_id_condition = switch_mprintf("call_id=%d", call_id);
486 } else {
487 call_id_condition = switch_mprintf("1=1");
488 }
489 switch_assert(call_id_condition)((call_id_condition) ? (void) (0) : __assert_fail ("call_id_condition"
, "mod_skinny.c", 489, __PRETTY_FUNCTION__))
;
490
491 helper.call_state = -1;
492 if ((sql = switch_mprintf(
493 "SELECT call_state FROM skinny_active_lines "
494 "WHERE device_name='%s' AND device_instance=%d "
495 "AND %s AND %s "
496 "ORDER BY call_state, channel_uuid", /* off hook first */
497 listener->device_name, listener->device_instance,
498 line_instance_condition, call_id_condition
499 ))) {
500 skinny_execute_sql_callback(listener->profile, listener->profile->sql_mutex, sql, skinny_line_get_state_callback, &helper);
501 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
502 }
503 switch_safe_free(line_instance_condition)if (line_instance_condition) {free(line_instance_condition);line_instance_condition
=((void*)0);}
;
504 switch_safe_free(call_id_condition)if (call_id_condition) {free(call_id_condition);call_id_condition
=((void*)0);}
;
505
506 return helper.call_state;
507}
508
509struct skinny_line_count_active_helper {
510 uint32_t count;
511};
512
513int skinny_line_count_active_callback(void *pArg, int argc, char **argv, char **columnNames)
514{
515 struct skinny_line_count_active_helper *helper = pArg;
516 helper->count++;
517 return 0;
518}
519
520uint32_t skinny_line_count_active(listener_t *listener)
521{
522 char *sql;
523 struct skinny_line_count_active_helper helper = {0};
524
525 switch_assert(listener)((listener) ? (void) (0) : __assert_fail ("listener", "mod_skinny.c"
, 525, __PRETTY_FUNCTION__))
;
526
527 helper.count = 0;
528 if ((sql = switch_mprintf(
529 "SELECT call_state FROM skinny_active_lines "
530 "WHERE device_name='%s' AND device_instance=%d "
531 "AND call_state not in (%d,%d,%d)",
532 listener->device_name, listener->device_instance,
533 SKINNY_ON_HOOK, SKINNY_IN_USE_REMOTELY, SKINNY_HOLD
534 ))) {
535
536 skinny_execute_sql_callback(listener->profile, listener->profile->sql_mutex, sql, skinny_line_count_active_callback, &helper);
537 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
538 }
539
540 return helper.count;
541}
542
543switch_status_t skinny_tech_set_codec(private_t *tech_pvt, int force)
544{
545 switch_status_t status = SWITCH_STATUS_SUCCESS;
546 int resetting = 0;
547
548 if (!tech_pvt->iananame) {
549 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 549, (const char*)(tech_pvt->session)
, SWITCH_LOG_ERROR, "No audio codec available\n");
550 switch_goto_status(SWITCH_STATUS_FALSE, end)status = SWITCH_STATUS_FALSE; goto end;
551 }
552
553 if (switch_core_codec_ready(&tech_pvt->read_codec)) {
554 if (!force) {
555 switch_goto_status(SWITCH_STATUS_SUCCESS, end)status = SWITCH_STATUS_SUCCESS; goto end;
556 }
557 if (strcasecmp(tech_pvt->read_impl.iananame, tech_pvt->iananame) ||
558 tech_pvt->read_impl.samples_per_second != tech_pvt->rm_rate ||
559 tech_pvt->codec_ms != (uint32_t)tech_pvt->read_impl.microseconds_per_packet / 1000) {
560
561 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 561, (const char*)(tech_pvt->session)
, SWITCH_LOG_DEBUG, "Changing Codec from %s@%dms to %s@%dms\n",
562 tech_pvt->read_impl.iananame, tech_pvt->read_impl.microseconds_per_packet / 1000,
563 tech_pvt->rm_encoding, tech_pvt->codec_ms);
564
565 switch_core_session_lock_codec_write(tech_pvt->session);
566 switch_core_session_lock_codec_read(tech_pvt->session);
567 resetting = 1;
568 switch_core_codec_destroy(&tech_pvt->read_codec);
569 switch_core_codec_destroy(&tech_pvt->write_codec);
570 } else {
571 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 571, (const char*)(tech_pvt->session)
, SWITCH_LOG_DEBUG, "Already using %s\n", tech_pvt->read_impl.iananame);
572 switch_goto_status(SWITCH_STATUS_SUCCESS, end)status = SWITCH_STATUS_SUCCESS; goto end;
573 }
574 }
575
576 if (switch_core_codec_init(&tech_pvt->read_codec,switch_core_codec_init_with_bitrate(&tech_pvt->read_codec
, tech_pvt->iananame, tech_pvt->rm_fmtp, tech_pvt->rm_rate
, tech_pvt->codec_ms, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
| 0, ((void*)0), switch_core_session_get_pool(tech_pvt->session
))
577 tech_pvt->iananame,switch_core_codec_init_with_bitrate(&tech_pvt->read_codec
, tech_pvt->iananame, tech_pvt->rm_fmtp, tech_pvt->rm_rate
, tech_pvt->codec_ms, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
| 0, ((void*)0), switch_core_session_get_pool(tech_pvt->session
))
578 tech_pvt->rm_fmtp,switch_core_codec_init_with_bitrate(&tech_pvt->read_codec
, tech_pvt->iananame, tech_pvt->rm_fmtp, tech_pvt->rm_rate
, tech_pvt->codec_ms, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
| 0, ((void*)0), switch_core_session_get_pool(tech_pvt->session
))
579 tech_pvt->rm_rate,switch_core_codec_init_with_bitrate(&tech_pvt->read_codec
, tech_pvt->iananame, tech_pvt->rm_fmtp, tech_pvt->rm_rate
, tech_pvt->codec_ms, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
| 0, ((void*)0), switch_core_session_get_pool(tech_pvt->session
))
580 tech_pvt->codec_ms,switch_core_codec_init_with_bitrate(&tech_pvt->read_codec
, tech_pvt->iananame, tech_pvt->rm_fmtp, tech_pvt->rm_rate
, tech_pvt->codec_ms, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
| 0, ((void*)0), switch_core_session_get_pool(tech_pvt->session
))
581 1,switch_core_codec_init_with_bitrate(&tech_pvt->read_codec
, tech_pvt->iananame, tech_pvt->rm_fmtp, tech_pvt->rm_rate
, tech_pvt->codec_ms, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
| 0, ((void*)0), switch_core_session_get_pool(tech_pvt->session
))
582 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | 0 /* TODO tech_pvt->profile->codec_flags */,switch_core_codec_init_with_bitrate(&tech_pvt->read_codec
, tech_pvt->iananame, tech_pvt->rm_fmtp, tech_pvt->rm_rate
, tech_pvt->codec_ms, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
| 0, ((void*)0), switch_core_session_get_pool(tech_pvt->session
))
583 NULL, switch_core_session_get_pool(tech_pvt->session))switch_core_codec_init_with_bitrate(&tech_pvt->read_codec
, tech_pvt->iananame, tech_pvt->rm_fmtp, tech_pvt->rm_rate
, tech_pvt->codec_ms, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
| 0, ((void*)0), switch_core_session_get_pool(tech_pvt->session
))
!= SWITCH_STATUS_SUCCESS) {
584 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 584, (const char*)(tech_pvt->session)
, SWITCH_LOG_ERROR, "Can't load codec?\n");
585 switch_goto_status(SWITCH_STATUS_FALSE, end)status = SWITCH_STATUS_FALSE; goto end;
586 }
587
588 if (switch_core_codec_init(&tech_pvt->write_codec,switch_core_codec_init_with_bitrate(&tech_pvt->write_codec
, tech_pvt->iananame, tech_pvt->rm_fmtp, tech_pvt->rm_rate
, tech_pvt->codec_ms, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
| 0, ((void*)0), switch_core_session_get_pool(tech_pvt->session
))
589 tech_pvt->iananame,switch_core_codec_init_with_bitrate(&tech_pvt->write_codec
, tech_pvt->iananame, tech_pvt->rm_fmtp, tech_pvt->rm_rate
, tech_pvt->codec_ms, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
| 0, ((void*)0), switch_core_session_get_pool(tech_pvt->session
))
590 tech_pvt->rm_fmtp,switch_core_codec_init_with_bitrate(&tech_pvt->write_codec
, tech_pvt->iananame, tech_pvt->rm_fmtp, tech_pvt->rm_rate
, tech_pvt->codec_ms, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
| 0, ((void*)0), switch_core_session_get_pool(tech_pvt->session
))
591 tech_pvt->rm_rate,switch_core_codec_init_with_bitrate(&tech_pvt->write_codec
, tech_pvt->iananame, tech_pvt->rm_fmtp, tech_pvt->rm_rate
, tech_pvt->codec_ms, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
| 0, ((void*)0), switch_core_session_get_pool(tech_pvt->session
))
592 tech_pvt->codec_ms,switch_core_codec_init_with_bitrate(&tech_pvt->write_codec
, tech_pvt->iananame, tech_pvt->rm_fmtp, tech_pvt->rm_rate
, tech_pvt->codec_ms, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
| 0, ((void*)0), switch_core_session_get_pool(tech_pvt->session
))
593 1,switch_core_codec_init_with_bitrate(&tech_pvt->write_codec
, tech_pvt->iananame, tech_pvt->rm_fmtp, tech_pvt->rm_rate
, tech_pvt->codec_ms, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
| 0, ((void*)0), switch_core_session_get_pool(tech_pvt->session
))
594 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | 0 /* TODO tech_pvt->profile->codec_flags */,switch_core_codec_init_with_bitrate(&tech_pvt->write_codec
, tech_pvt->iananame, tech_pvt->rm_fmtp, tech_pvt->rm_rate
, tech_pvt->codec_ms, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
| 0, ((void*)0), switch_core_session_get_pool(tech_pvt->session
))
595 NULL, switch_core_session_get_pool(tech_pvt->session))switch_core_codec_init_with_bitrate(&tech_pvt->write_codec
, tech_pvt->iananame, tech_pvt->rm_fmtp, tech_pvt->rm_rate
, tech_pvt->codec_ms, 1, 0, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE
| 0, ((void*)0), switch_core_session_get_pool(tech_pvt->session
))
!= SWITCH_STATUS_SUCCESS) {
596 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 596, (const char*)(tech_pvt->session)
, SWITCH_LOG_ERROR, "Can't load codec?\n");
597 switch_goto_status(SWITCH_STATUS_FALSE, end)status = SWITCH_STATUS_FALSE; goto end;
598 }
599
600 switch_assert(tech_pvt->read_codec.implementation)((tech_pvt->read_codec.implementation) ? (void) (0) : __assert_fail
("tech_pvt->read_codec.implementation", "mod_skinny.c", 600
, __PRETTY_FUNCTION__))
;
601 switch_assert(tech_pvt->write_codec.implementation)((tech_pvt->write_codec.implementation) ? (void) (0) : __assert_fail
("tech_pvt->write_codec.implementation", "mod_skinny.c", 601
, __PRETTY_FUNCTION__))
;
602
603 tech_pvt->read_impl = *tech_pvt->read_codec.implementation;
604 tech_pvt->write_impl = *tech_pvt->write_codec.implementation;
605
606 switch_core_session_set_read_impl(tech_pvt->session, tech_pvt->read_codec.implementation);
607 switch_core_session_set_write_impl(tech_pvt->session, tech_pvt->write_codec.implementation);
608
609 if (switch_rtp_ready(tech_pvt->rtp_session)) {
610 switch_assert(tech_pvt->read_codec.implementation)((tech_pvt->read_codec.implementation) ? (void) (0) : __assert_fail
("tech_pvt->read_codec.implementation", "mod_skinny.c", 610
, __PRETTY_FUNCTION__))
;
611
612 if (switch_rtp_change_interval(tech_pvt->rtp_session,
613 tech_pvt->read_impl.microseconds_per_packet,
614 tech_pvt->read_impl.samples_per_packet
615 ) != SWITCH_STATUS_SUCCESS) {
616 switch_channel_t *channel = switch_core_session_get_channel(tech_pvt->session);
617
618 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(channel, "mod_skinny.c", (const
char *)__func__, 618, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)
;
619 switch_goto_status(SWITCH_STATUS_FALSE, end)status = SWITCH_STATUS_FALSE; goto end;
620 }
621 }
622
623 tech_pvt->read_frame.rate = tech_pvt->rm_rate;
624 //ms = tech_pvt->write_codec.implementation->microseconds_per_packet / 1000;
625
626 if (!switch_core_codec_ready(&tech_pvt->read_codec)) {
627 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 627, (const char*)(tech_pvt->session)
, SWITCH_LOG_ERROR, "Can't load codec?\n");
628 switch_goto_status(SWITCH_STATUS_FALSE, end)status = SWITCH_STATUS_FALSE; goto end;
629 }
630
631 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 631, (const char*)(tech_pvt->session)
, SWITCH_LOG_DEBUG, "Set Codec %s %s/%ld %d ms %d samples\n",
632 "" /* TODO switch_channel_get_name(tech_pvt->channel)*/, tech_pvt->iananame, tech_pvt->rm_rate, tech_pvt->codec_ms,
633 tech_pvt->read_impl.samples_per_packet);
634 tech_pvt->read_frame.codec = &tech_pvt->read_codec;
635
636 tech_pvt->write_codec.agreed_pt = tech_pvt->agreed_pt;
637 tech_pvt->read_codec.agreed_pt = tech_pvt->agreed_pt;
638
639 if (force != 2) {
640 switch_core_session_set_read_codec(tech_pvt->session, &tech_pvt->read_codec);
641 switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->write_codec);
642 }
643
644 /* TODO
645 tech_pvt->fmtp_out = switch_core_session_strdup(tech_pvt->session, tech_pvt->write_codec.fmtp_out);
646 */
647
648 /* TODO
649 if (switch_rtp_ready(tech_pvt->rtp_session)) {
650 switch_rtp_set_default_payload(tech_pvt->rtp_session, tech_pvt->pt);
651 }
652 */
653
654end:
655 if (resetting) {
656 switch_core_session_unlock_codec_write(tech_pvt->session);
657 switch_core_session_unlock_codec_read(tech_pvt->session);
658 }
659
660 return status;
661}
662
663void tech_init(private_t *tech_pvt, skinny_profile_t *profile, switch_core_session_t *session)
664{
665 switch_assert(tech_pvt)((tech_pvt) ? (void) (0) : __assert_fail ("tech_pvt", "mod_skinny.c"
, 665, __PRETTY_FUNCTION__))
;
666 switch_assert(session)((session) ? (void) (0) : __assert_fail ("session", "mod_skinny.c"
, 666, __PRETTY_FUNCTION__))
;
667
668 tech_pvt->read_frame.data = tech_pvt->databuf;
669 tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf);
670 switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED0x1, switch_core_session_get_pool(session));
671 switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED0x1, switch_core_session_get_pool(session));
672 tech_pvt->profile = profile;
673 tech_pvt->call_id = ++profile->next_call_id;
674 tech_pvt->party_id = tech_pvt->call_id;
675 switch_core_session_set_private(session, tech_pvt)switch_core_session_set_private_class(session, tech_pvt, SWITCH_PVT_PRIMARY
)
;
676 tech_pvt->session = session;
677}
678
679/*
680 State methods they get called when the state changes to the specific state
681 returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
682 so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
683 */
684switch_status_t channel_on_init(switch_core_session_t *session)
685{
686 switch_channel_t *channel = switch_core_session_get_channel(session);
687
688 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 688, (const char*)(session)
, SWITCH_LOG_DEBUG, "%s CHANNEL INIT\n", switch_channel_get_name(channel));
689
690 /* This does not set the state to routing like most modules do, this now happens in the default state handeler so return FALSE TO BLOCK IT*/
691 return SWITCH_STATUS_FALSE;
692}
693
694struct channel_on_routing_helper {
695 private_t *tech_pvt;
696 listener_t *listener;
697 uint32_t line_instance;
698};
699
700int channel_on_routing_callback(void *pArg, int argc, char **argv, char **columnNames)
701{
702 struct channel_on_routing_helper *helper = pArg;
703 listener_t *listener = NULL((void*)0);
704 char *label;
705
706 char *device_name = argv[0];
707 uint32_t device_instance = atoi(argv[1]);
708 /* uint32_t position = atoi(argv[2]); */
709 uint32_t line_instance = atoi(argv[3]);
710 /* char *label = argv[4]; */
711 /* char *value = argv[5]; */
712 /* char *caller_name = argv[6]; */
713 /* uint32_t ring_on_idle = atoi(argv[7]); */
714 /* uint32_t ring_on_active = atoi(argv[8]); */
715 /* uint32_t busy_trigger = atoi(argv[9]); */
716 /* char *forward_all = argv[10]; */
717 /* char *forward_busy = argv[11]; */
718 /* char *forward_noanswer = argv[12]; */
719 /* uint32_t noanswer_duration = atoi(argv[13]); */
720 /* char *channel_uuid = argv[14]; */
721 /* uint32_t call_id = atoi(argv[15]); */
722 /* uint32_t call_state = atoi(argv[16]); */
723
724 skinny_profile_find_listener_by_device_name_and_instance(helper->tech_pvt->profile, device_name, device_instance, &listener);
725 if(listener) {
726 if(!strcmp(device_name, helper->listener->device_name)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(device_name) && __builtin_constant_p (helper->listener
->device_name) && (__s1_len = __builtin_strlen (device_name
), __s2_len = __builtin_strlen (helper->listener->device_name
), (!((size_t)(const void *)((device_name) + 1) - (size_t)(const
void *)(device_name) == 1) || __s1_len >= 4) && (
!((size_t)(const void *)((helper->listener->device_name
) + 1) - (size_t)(const void *)(helper->listener->device_name
) == 1) || __s2_len >= 4)) ? __builtin_strcmp (device_name
, helper->listener->device_name) : (__builtin_constant_p
(device_name) && ((size_t)(const void *)((device_name
) + 1) - (size_t)(const void *)(device_name) == 1) &&
(__s1_len = __builtin_strlen (device_name), __s1_len < 4)
? (__builtin_constant_p (helper->listener->device_name
) && ((size_t)(const void *)((helper->listener->
device_name) + 1) - (size_t)(const void *)(helper->listener
->device_name) == 1) ? __builtin_strcmp (device_name, helper
->listener->device_name) : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (helper->
listener->device_name); int __result = (((const unsigned char
*) (const char *) (device_name))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (device_name))[1] - __s2[1]); if (__s1_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) (device_name))[2] - __s2[2]); if (__s1_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (device_name))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p (helper->listener->device_name
) && ((size_t)(const void *)((helper->listener->
device_name) + 1) - (size_t)(const void *)(helper->listener
->device_name) == 1) && (__s2_len = __builtin_strlen
(helper->listener->device_name), __s2_len < 4) ? (__builtin_constant_p
(device_name) && ((size_t)(const void *)((device_name
) + 1) - (size_t)(const void *)(device_name) == 1) ? __builtin_strcmp
(device_name, helper->listener->device_name) : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (device_name); int __result = (((const unsigned char
*) (const char *) (helper->listener->device_name))[0] -
__s2[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (helper->listener
->device_name))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (helper->listener->device_name))[2] - __s2[2])
; if (__s2_len > 2 && __result == 0) __result = ((
(const unsigned char *) (const char *) (helper->listener->
device_name))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(device_name, helper->listener->device_name)))); })
727 && (device_instance == helper->listener->device_instance)
728 && (line_instance == helper->line_instance)) {/* the calling line */
729 helper->tech_pvt->caller_profile->dialplan = switch_core_strdup(helper->tech_pvt->caller_profile->pool, listener->profile->dialplan)switch_core_perform_strdup(helper->tech_pvt->caller_profile
->pool, listener->profile->dialplan, "mod_skinny.c",
(const char *)__func__, 729)
;
730 helper->tech_pvt->caller_profile->context = switch_core_strdup(helper->tech_pvt->caller_profile->pool, listener->profile->context)switch_core_perform_strdup(helper->tech_pvt->caller_profile
->pool, listener->profile->context, "mod_skinny.c", (
const char *)__func__, 730)
;
731 send_dialed_number(listener, helper->tech_pvt->caller_profile->destination_number, line_instance, helper->tech_pvt->call_id)perform_send_dialed_number(listener, "mod_skinny.c", (const char
*)__func__, 731, helper->tech_pvt->caller_profile->
destination_number, line_instance, helper->tech_pvt->call_id
)
;
732 skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_PROCEED)skinny_line_perform_set_state("mod_skinny.c", (const char *)__func__
, 732, listener, line_instance, helper->tech_pvt->call_id
, SKINNY_PROCEED)
;
733 skinny_session_send_call_info(helper->tech_pvt->session, listener, line_instance);
734 skinny_session_ring_out(helper->tech_pvt->session, listener, line_instance);
735 } else {
736 send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_ON)perform_send_set_lamp(listener, "mod_skinny.c", (const char *
)__func__, 736, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_ON
)
;
737 skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_IN_USE_REMOTELY)skinny_line_perform_set_state("mod_skinny.c", (const char *)__func__
, 737, listener, line_instance, helper->tech_pvt->call_id
, SKINNY_IN_USE_REMOTELY)
;
738 send_select_soft_keys(listener, line_instance, helper->tech_pvt->call_id, SKINNY_KEY_SET_IN_USE_HINT, 0xffff)perform_send_select_soft_keys(listener, "mod_skinny.c", (const
char *)__func__, 738, line_instance, helper->tech_pvt->
call_id, SKINNY_KEY_SET_IN_USE_HINT, 0xffff)
;
739
740 label = skinny_textid2raw(SKINNY_TEXTID_IN_USE_REMOTE)(SKINNY_TEXTID_IN_USE_REMOTE > 0 ? switch_mprintf("\200%c"
, SKINNY_TEXTID_IN_USE_REMOTE) : switch_mprintf(""))
;
741 send_display_prompt_status(listener, 0, label, line_instance, helper->tech_pvt->call_id)perform_send_display_prompt_status(listener, "mod_skinny.c", (
const char *)__func__, 741, 0, label, line_instance, helper->
tech_pvt->call_id)
;
742 switch_safe_free(label)if (label) {free(label);label=((void*)0);};
743
744 skinny_session_send_call_info(helper->tech_pvt->session, listener, line_instance);
745 }
746 }
747 return 0;
748}
749
750switch_status_t channel_on_routing(switch_core_session_t *session)
751{
752 switch_channel_t *channel = switch_core_session_get_channel(session);
753 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
754 skinny_action_t action;
755 private_t *tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
756 char *data = NULL((void*)0);
757 listener_t *listener = NULL((void*)0);
758 struct channel_on_routing_helper helper = {0};
759 int digit_timeout;
760
761 if(switch_test_flag(tech_pvt, TFLAG_FORCE_ROUTE)((tech_pvt)->flags & TFLAG_FORCE_ROUTE)) {
762 action = SKINNY_ACTION_PROCESS;
763 } else {
764 action = skinny_session_dest_match_pattern(session, &data);
765 }
766 switch(action) {
767 case SKINNY_ACTION_PROCESS:
768 skinny_profile_find_listener_by_device_name_and_instance(tech_pvt->profile,
769 switch_channel_get_variable(channel, "skinny_device_name")switch_channel_get_variable_dup(channel, "skinny_device_name"
, SWITCH_TRUE, -1)
,
770 atoi(switch_channel_get_variable(channel, "skinny_device_instance")switch_channel_get_variable_dup(channel, "skinny_device_instance"
, SWITCH_TRUE, -1)
), &listener);
771 if (listener) {
772 helper.tech_pvt = tech_pvt;
773 helper.listener = listener;
774 helper.line_instance = atoi(switch_channel_get_variable(channel, "skinny_line_instance")switch_channel_get_variable_dup(channel, "skinny_line_instance"
, SWITCH_TRUE, -1)
);
775 skinny_session_walk_lines(tech_pvt->profile, switch_core_session_get_uuid(session), channel_on_routing_callback, &helper);
776
777 /* clear digit timeout time */
778 listener->digit_timeout_time = 0;
779 } else {
780 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 780, (const char*)(session)
, SWITCH_LOG_WARNING, "Could not find listener %s:%s for Channel %s\n",
781 switch_channel_get_variable(channel, "skinny_device_name")switch_channel_get_variable_dup(channel, "skinny_device_name"
, SWITCH_TRUE, -1)
, switch_channel_get_variable(channel, "skinny_device_instance")switch_channel_get_variable_dup(channel, "skinny_device_instance"
, SWITCH_TRUE, -1)
,
782 switch_channel_get_name(channel));
783 }
784
785 /* Future bridge should go straight */
786 switch_set_flag_locked(tech_pvt, TFLAG_FORCE_ROUTE)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != ((void*)0)", "mod_skinny.c", 786
, __PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags |= (TFLAG_FORCE_ROUTE);switch_mutex_unlock
(tech_pvt->flag_mutex);
;
787 break;
788 case SKINNY_ACTION_WAIT:
789 /* for now, wait forever */
790 switch_channel_set_state(channel, CS_HIBERNATE)switch_channel_perform_set_state(channel, "mod_skinny.c", (const
char *)__func__, 790, CS_HIBERNATE)
;
791 skinny_profile_find_listener_by_device_name_and_instance(tech_pvt->profile,
792 switch_channel_get_variable(channel, "skinny_device_name")switch_channel_get_variable_dup(channel, "skinny_device_name"
, SWITCH_TRUE, -1)
,
793 atoi(switch_channel_get_variable(channel, "skinny_device_instance")switch_channel_get_variable_dup(channel, "skinny_device_instance"
, SWITCH_TRUE, -1)
), &listener);
794
795 if (listener) {
796 digit_timeout = listener->profile->digit_timeout;
797 if (!zstr(data)_zstr(data)) {
798 digit_timeout = atoi(data);
799 if ( digit_timeout < 100 ) {
800 digit_timeout *= 1000;
801 }
802 }
803
804 listener->digit_timeout_time = switch_mono_micro_time_now() + digit_timeout * 1000;
805 } else {
806 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 806, (const char*)(session)
, SWITCH_LOG_WARNING, "Could not find listener %s:%s for Channel %s\n",
807 switch_channel_get_variable(channel, "skinny_device_name")switch_channel_get_variable_dup(channel, "skinny_device_name"
, SWITCH_TRUE, -1)
, switch_channel_get_variable(channel, "skinny_device_instance")switch_channel_get_variable_dup(channel, "skinny_device_instance"
, SWITCH_TRUE, -1)
,
808 switch_channel_get_name(channel));
809
810 }
811
812 break;
813 case SKINNY_ACTION_DROP:
814 default:
815 switch_channel_hangup(channel, SWITCH_CAUSE_UNALLOCATED_NUMBER)switch_channel_perform_hangup(channel, "mod_skinny.c", (const
char *)__func__, 815, SWITCH_CAUSE_UNALLOCATED_NUMBER)
;
816 }
817 }
818
819 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 819, (const char*)(session)
, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel));
820
821 return SWITCH_STATUS_SUCCESS;
822}
823
824struct channel_on_execute_helper {
825 private_t *tech_pvt;
826 listener_t *listener;
827 uint32_t line_instance;
828};
829
830int channel_on_execute_callback(void *pArg, int argc, char **argv, char **columnNames)
831{
832 struct channel_on_routing_helper *helper = pArg;
833 listener_t *listener = NULL((void*)0);
834
835 char *device_name = argv[0];
836 uint32_t device_instance = atoi(argv[1]);
837 /* uint32_t position = atoi(argv[2]); */
838 uint32_t line_instance = atoi(argv[3]);
839 /* char *label = argv[4]; */
840 /* char *value = argv[5]; */
841 /* char *caller_name = argv[6]; */
842 /* uint32_t ring_on_idle = atoi(argv[7]); */
843 /* uint32_t ring_on_active = atoi(argv[8]); */
844 /* uint32_t busy_trigger = atoi(argv[9]); */
845 /* char *forward_all = argv[10]; */
846 /* char *forward_busy = argv[11]; */
847 /* char *forward_noanswer = argv[12]; */
848 /* uint32_t noanswer_duration = atoi(argv[13]); */
849 /* char *channel_uuid = argv[14]; */
850 /* uint32_t call_id = atoi(argv[15]); */
851 /* uint32_t call_state = atoi(argv[16]); */
852
853 skinny_profile_find_listener_by_device_name_and_instance(helper->tech_pvt->profile, device_name, device_instance, &listener);
854 if(listener) {
855 if(!strcmp(device_name, helper->listener->device_name)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(device_name) && __builtin_constant_p (helper->listener
->device_name) && (__s1_len = __builtin_strlen (device_name
), __s2_len = __builtin_strlen (helper->listener->device_name
), (!((size_t)(const void *)((device_name) + 1) - (size_t)(const
void *)(device_name) == 1) || __s1_len >= 4) && (
!((size_t)(const void *)((helper->listener->device_name
) + 1) - (size_t)(const void *)(helper->listener->device_name
) == 1) || __s2_len >= 4)) ? __builtin_strcmp (device_name
, helper->listener->device_name) : (__builtin_constant_p
(device_name) && ((size_t)(const void *)((device_name
) + 1) - (size_t)(const void *)(device_name) == 1) &&
(__s1_len = __builtin_strlen (device_name), __s1_len < 4)
? (__builtin_constant_p (helper->listener->device_name
) && ((size_t)(const void *)((helper->listener->
device_name) + 1) - (size_t)(const void *)(helper->listener
->device_name) == 1) ? __builtin_strcmp (device_name, helper
->listener->device_name) : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (helper->
listener->device_name); int __result = (((const unsigned char
*) (const char *) (device_name))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (device_name))[1] - __s2[1]); if (__s1_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) (device_name))[2] - __s2[2]); if (__s1_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (device_name))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p (helper->listener->device_name
) && ((size_t)(const void *)((helper->listener->
device_name) + 1) - (size_t)(const void *)(helper->listener
->device_name) == 1) && (__s2_len = __builtin_strlen
(helper->listener->device_name), __s2_len < 4) ? (__builtin_constant_p
(device_name) && ((size_t)(const void *)((device_name
) + 1) - (size_t)(const void *)(device_name) == 1) ? __builtin_strcmp
(device_name, helper->listener->device_name) : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (device_name); int __result = (((const unsigned char
*) (const char *) (helper->listener->device_name))[0] -
__s2[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (helper->listener
->device_name))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (helper->listener->device_name))[2] - __s2[2])
; if (__s2_len > 2 && __result == 0) __result = ((
(const unsigned char *) (const char *) (helper->listener->
device_name))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(device_name, helper->listener->device_name)))); })
856 && (device_instance == helper->listener->device_instance)
857 && (line_instance == helper->line_instance)) {/* the calling line */
858 helper->tech_pvt->caller_profile->dialplan = switch_core_strdup(helper->tech_pvt->caller_profile->pool, listener->profile->dialplan)switch_core_perform_strdup(helper->tech_pvt->caller_profile
->pool, listener->profile->dialplan, "mod_skinny.c",
(const char *)__func__, 858)
;
859 helper->tech_pvt->caller_profile->context = switch_core_strdup(helper->tech_pvt->caller_profile->pool, listener->profile->context)switch_core_perform_strdup(helper->tech_pvt->caller_profile
->pool, listener->profile->context, "mod_skinny.c", (
const char *)__func__, 859)
;
860
861 send_stop_tone(listener, line_instance, helper->tech_pvt->call_id)perform_send_stop_tone(listener, "mod_skinny.c", (const char *
)__func__, 861, line_instance, helper->tech_pvt->call_id
)
;
862 } else {
863 }
864 }
865 return 0;
866}
867
868switch_status_t channel_on_execute(switch_core_session_t *session)
869{
870 switch_channel_t *channel = switch_core_session_get_channel(session);
871
872 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
873 private_t *tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
874 listener_t *listener = NULL((void*)0);
875 struct channel_on_execute_helper helper = {0};
876
877 skinny_profile_find_listener_by_device_name_and_instance(tech_pvt->profile,
878 switch_channel_get_variable(channel, "skinny_device_name")switch_channel_get_variable_dup(channel, "skinny_device_name"
, SWITCH_TRUE, -1)
,
879 atoi(switch_channel_get_variable(channel, "skinny_device_instance")switch_channel_get_variable_dup(channel, "skinny_device_instance"
, SWITCH_TRUE, -1)
), &listener);
880 if (listener) {
881 helper.tech_pvt = tech_pvt;
882 helper.listener = listener;
883 helper.line_instance = atoi(switch_channel_get_variable(channel, "skinny_line_instance")switch_channel_get_variable_dup(channel, "skinny_line_instance"
, SWITCH_TRUE, -1)
);
884 skinny_session_walk_lines(tech_pvt->profile, switch_core_session_get_uuid(session), channel_on_execute_callback, &helper);
885 } else {
886 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 886, (const char*)(session)
, SWITCH_LOG_WARNING, "Could not find listener %s:%s for Channel %s\n",
887 switch_channel_get_variable(channel, "skinny_device_name")switch_channel_get_variable_dup(channel, "skinny_device_name"
, SWITCH_TRUE, -1)
, switch_channel_get_variable(channel, "skinny_device_instance")switch_channel_get_variable_dup(channel, "skinny_device_instance"
, SWITCH_TRUE, -1)
,
888 switch_channel_get_name(channel));
889 }
890 }
891 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 891, (const char*)(session)
, SWITCH_LOG_DEBUG, "%s CHANNEL EXECUTE\n", switch_channel_get_name(channel));
892
893 return SWITCH_STATUS_SUCCESS;
894}
895
896switch_status_t channel_on_destroy(switch_core_session_t *session)
897{
898 switch_channel_t *channel = switch_core_session_get_channel(session);
899 private_t *tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
900
901 if (tech_pvt) {
902 if (switch_core_codec_ready(&tech_pvt->read_codec)) {
903 switch_core_codec_destroy(&tech_pvt->read_codec);
904 }
905
906 if (switch_core_codec_ready(&tech_pvt->write_codec)) {
907 switch_core_codec_destroy(&tech_pvt->write_codec);
908 }
909
910 if (switch_rtp_ready(tech_pvt->rtp_session)) {
911 switch_rtp_destroy(&tech_pvt->rtp_session);
912 }
913 }
914
915 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 915, (const char*)(session)
, SWITCH_LOG_DEBUG, "%s CHANNEL DESTROY\n", switch_channel_get_name(channel));
916
917 return SWITCH_STATUS_SUCCESS;
918}
919
920struct channel_on_hangup_helper {
921 private_t *tech_pvt;
922 switch_call_cause_t cause;
923};
924
925int channel_on_hangup_callback(void *pArg, int argc, char **argv, char **columnNames)
926{
927 struct channel_on_hangup_helper *helper = pArg;
928 listener_t *listener = NULL((void*)0);
929 char *label;
930
931 char *device_name = argv[0];
932 uint32_t device_instance = atoi(argv[1]);
933 /* uint32_t position = atoi(argv[2]); */
934 uint32_t line_instance = atoi(argv[3]);
935 /* char *label = argv[4]; */
936 /* char *value = argv[5]; */
937 /* char *caller_name = argv[6]; */
938 /* uint32_t ring_on_idle = atoi(argv[7]); */
939 /* uint32_t ring_on_active = atoi(argv[8]); */
940 /* uint32_t busy_trigger = atoi(argv[9]); */
941 /* char *forward_all = argv[10]; */
942 /* char *forward_busy = argv[11]; */
943 /* char *forward_noanswer = argv[12]; */
944 /* uint32_t noanswer_duration = atoi(argv[13]); */
945 /* char *channel_uuid = argv[14]; */
946 uint32_t call_id = atoi(argv[15]);
947 uint32_t call_state = atoi(argv[16]);
948
949 skinny_profile_find_listener_by_device_name_and_instance(helper->tech_pvt->profile, device_name, device_instance, &listener);
950 if(listener) {
951 if((call_state == SKINNY_PROCEED) || (call_state == SKINNY_CONNECTED)) { /* calling parties */
952 send_stop_tone(listener, line_instance, call_id)perform_send_stop_tone(listener, "mod_skinny.c", (const char *
)__func__, 952, line_instance, call_id)
;
953 send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_OFF)perform_send_set_lamp(listener, "mod_skinny.c", (const char *
)__func__, 953, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_OFF
)
;
954 send_clear_prompt_status(listener, line_instance, call_id)perform_send_clear_prompt_status(listener, "mod_skinny.c", (const
char *)__func__, 954, line_instance, call_id)
;
955 }
956 send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_OFF)perform_send_set_lamp(listener, "mod_skinny.c", (const char *
)__func__, 956, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_OFF
)
;
957
958 if((call_state == SKINNY_PROCEED) || (call_state == SKINNY_RING_OUT) || (call_state == SKINNY_CONNECTED)) { /* calling parties */
959 switch (helper->cause) {
960 case SWITCH_CAUSE_UNALLOCATED_NUMBER:
961 send_start_tone(listener, SKINNY_TONE_REORDER, 0, line_instance, call_id)perform_send_start_tone(listener, "mod_skinny.c", (const char
*)__func__, 961, SKINNY_TONE_REORDER, 0, line_instance, call_id
)
;
962 skinny_session_send_call_info(helper->tech_pvt->session, listener, line_instance);
963 label = skinny_textid2raw(SKINNY_TEXTID_UNKNOWN_NUMBER)(SKINNY_TEXTID_UNKNOWN_NUMBER > 0 ? switch_mprintf("\200%c"
, SKINNY_TEXTID_UNKNOWN_NUMBER) : switch_mprintf(""))
;
964 send_display_prompt_status(listener, 0, label, line_instance, call_id)perform_send_display_prompt_status(listener, "mod_skinny.c", (
const char *)__func__, 964, 0, label, line_instance, call_id)
;
965 switch_safe_free(label)if (label) {free(label);label=((void*)0);};
966 break;
967 case SWITCH_CAUSE_USER_BUSY:
968 send_start_tone(listener, SKINNY_TONE_BUSYTONE, 0, line_instance, call_id)perform_send_start_tone(listener, "mod_skinny.c", (const char
*)__func__, 968, SKINNY_TONE_BUSYTONE, 0, line_instance, call_id
)
;
969 label = skinny_textid2raw(SKINNY_TEXTID_BUSY)(SKINNY_TEXTID_BUSY > 0 ? switch_mprintf("\200%c", SKINNY_TEXTID_BUSY
) : switch_mprintf(""))
;
970 send_display_prompt_status(listener, 0, label, line_instance, call_id)perform_send_display_prompt_status(listener, "mod_skinny.c", (
const char *)__func__, 970, 0, label, line_instance, call_id)
;
971 switch_safe_free(label)if (label) {free(label);label=((void*)0);};
972 break;
973 case SWITCH_CAUSE_NORMAL_CLEARING:
974 send_clear_prompt_status(listener, line_instance, call_id)perform_send_clear_prompt_status(listener, "mod_skinny.c", (const
char *)__func__, 974, line_instance, call_id)
;
975 break;
976 default:
977 send_display_prompt_status(listener, 0, switch_channel_cause2str(helper->cause), line_instance, call_id)perform_send_display_prompt_status(listener, "mod_skinny.c", (
const char *)__func__, 977, 0, switch_channel_cause2str(helper
->cause), line_instance, call_id)
;
978 }
979
980 skinny_session_stop_media(helper->tech_pvt->session, listener, line_instance);
981 }
982
983 skinny_line_set_state(listener, line_instance, call_id, SKINNY_ON_HOOK)skinny_line_perform_set_state("mod_skinny.c", (const char *)__func__
, 983, listener, line_instance, call_id, SKINNY_ON_HOOK)
;
984 send_select_soft_keys(listener, line_instance, call_id, SKINNY_KEY_SET_ON_HOOK, 0xffff)perform_send_select_soft_keys(listener, "mod_skinny.c", (const
char *)__func__, 984, line_instance, call_id, SKINNY_KEY_SET_ON_HOOK
, 0xffff)
;
985 send_define_current_time_date(listener)perform_send_define_current_time_date(listener, "mod_skinny.c"
, (const char *)__func__, 985)
;
986 listener->digit_timeout_time = 0;
987
988 skinny_log_ls(listener, helper->tech_pvt->session, SWITCH_LOG_DEBUG,switch_log_printf(SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (
const char *)__func__, 991, (const char*)(helper->tech_pvt
->session), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] " "channel_on_hangup_callback - cause=%s [%d], call_state = %s [%d]\n"
, (_zstr(listener->device_name) ? "_undef_" : listener->
device_name), listener->device_instance, (_zstr(listener->
remote_ip) ? "_undef_" : listener->remote_ip), listener->
remote_port, switch_channel_cause2str(helper->cause), helper
->cause, skinny_call_state2str(call_state), call_state)
989 "channel_on_hangup_callback - cause=%s [%d], call_state = %s [%d]\n",switch_log_printf(SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (
const char *)__func__, 991, (const char*)(helper->tech_pvt
->session), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] " "channel_on_hangup_callback - cause=%s [%d], call_state = %s [%d]\n"
, (_zstr(listener->device_name) ? "_undef_" : listener->
device_name), listener->device_instance, (_zstr(listener->
remote_ip) ? "_undef_" : listener->remote_ip), listener->
remote_port, switch_channel_cause2str(helper->cause), helper
->cause, skinny_call_state2str(call_state), call_state)
990 switch_channel_cause2str(helper->cause), helper->cause,switch_log_printf(SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (
const char *)__func__, 991, (const char*)(helper->tech_pvt
->session), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] " "channel_on_hangup_callback - cause=%s [%d], call_state = %s [%d]\n"
, (_zstr(listener->device_name) ? "_undef_" : listener->
device_name), listener->device_instance, (_zstr(listener->
remote_ip) ? "_undef_" : listener->remote_ip), listener->
remote_port, switch_channel_cause2str(helper->cause), helper
->cause, skinny_call_state2str(call_state), call_state)
991 skinny_call_state2str(call_state), call_state)switch_log_printf(SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (
const char *)__func__, 991, (const char*)(helper->tech_pvt
->session), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] " "channel_on_hangup_callback - cause=%s [%d], call_state = %s [%d]\n"
, (_zstr(listener->device_name) ? "_undef_" : listener->
device_name), listener->device_instance, (_zstr(listener->
remote_ip) ? "_undef_" : listener->remote_ip), listener->
remote_port, switch_channel_cause2str(helper->cause), helper
->cause, skinny_call_state2str(call_state), call_state)
;
992
993 if ( call_state == SKINNY_RING_OUT && helper->cause == SWITCH_CAUSE_USER_BUSY )
994 {
995 // don't hang up speaker here
996 }
997 else if((call_state == SKINNY_PROCEED) || (call_state == SKINNY_RING_OUT) || (call_state == SKINNY_CONNECTED)) { /* calling parties */
998 // This is NOT correct, but results in slightly better behavior than before
999 // leaving note here to revisit.
1000
1001 /* re-enabling for testing to bring back bad behavior */
1002 send_set_speaker_mode(listener, SKINNY_SPEAKER_OFF)perform_send_set_speaker_mode(listener, "mod_skinny.c", (const
char *)__func__, 1002, SKINNY_SPEAKER_OFF)
;
1003 }
1004 send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, line_instance, call_id)perform_send_set_ringer(listener, "mod_skinny.c", (const char
*)__func__, 1004, SKINNY_RING_OFF, SKINNY_RING_FOREVER, line_instance
, call_id)
;
1005 }
1006 return 0;
1007}
1008
1009switch_status_t channel_on_hangup(switch_core_session_t *session)
1010{
1011 struct channel_on_hangup_helper helper = {0};
1012 switch_channel_t *channel = switch_core_session_get_channel(session);
1013 switch_call_cause_t cause = switch_channel_get_cause(channel);
1014 private_t *tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
1015 char *sql;
1016
1017 switch_clear_flag_locked(tech_pvt, TFLAG_IO)switch_mutex_lock(tech_pvt->flag_mutex); (tech_pvt)->flags
&= ~(TFLAG_IO); switch_mutex_unlock(tech_pvt->flag_mutex
);
;
1018
1019 skinny_log_s(session, SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP [%s]\n",switch_log_printf(SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (
const char *)__func__, 1020, (const char*)(session), SWITCH_LOG_DEBUG
, "%s CHANNEL HANGUP [%s]\n", switch_channel_get_name(channel
), switch_channel_cause2str(cause))
1020 switch_channel_get_name(channel), switch_channel_cause2str(cause))switch_log_printf(SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (
const char *)__func__, 1020, (const char*)(session), SWITCH_LOG_DEBUG
, "%s CHANNEL HANGUP [%s]\n", switch_channel_get_name(channel
), switch_channel_cause2str(cause))
;
1021
1022 helper.tech_pvt= tech_pvt;
1023 helper.cause= cause;
1024
1025 skinny_session_walk_lines(tech_pvt->profile, switch_core_session_get_uuid(session), channel_on_hangup_callback, &helper);
1026 if ((sql = switch_mprintf(
1027 "DELETE FROM skinny_active_lines WHERE channel_uuid='%q'",
1028 switch_core_session_get_uuid(session)
1029 ))) {
1030 skinny_execute_sql(tech_pvt->profile, sql, tech_pvt->profile->sql_mutex);
1031 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1032 }
1033 return SWITCH_STATUS_SUCCESS;
1034}
1035
1036switch_status_t channel_kill_channel(switch_core_session_t *session, int sig)
1037{
1038 switch_channel_t *channel = switch_core_session_get_channel(session);
1039 private_t *tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
1040
1041 switch (sig) {
1042 case SWITCH_SIG_KILL:
1043 switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING)switch_channel_perform_hangup(channel, "mod_skinny.c", (const
char *)__func__, 1043, SWITCH_CAUSE_NORMAL_CLEARING)
;
1044 break;
1045 case SWITCH_SIG_BREAK:
1046 if (switch_rtp_ready(tech_pvt->rtp_session)) {
1047 switch_rtp_break(tech_pvt->rtp_session);
1048 }
1049 break;
1050 default:
1051 break;
1052 }
1053
1054 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 1054, (const char*)(session)
, SWITCH_LOG_DEBUG, "%s CHANNEL KILL %d\n", switch_channel_get_name(channel), sig);
1055
1056 return SWITCH_STATUS_SUCCESS;
1057}
1058
1059switch_status_t channel_on_exchange_media(switch_core_session_t *session)
1060{
1061 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 1061, (const char*)(session)
, SWITCH_LOG_DEBUG, "CHANNEL LOOPBACK\n");
1062 return SWITCH_STATUS_SUCCESS;
1063}
1064
1065switch_status_t channel_on_soft_execute(switch_core_session_t *session)
1066{
1067 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 1067, (const char*)(session)
, SWITCH_LOG_DEBUG, "CHANNEL TRANSMIT\n");
1068 return SWITCH_STATUS_SUCCESS;
1069}
1070
1071switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
1072{
1073 private_t *tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
1074 switch_assert(tech_pvt != NULL)((tech_pvt != ((void*)0)) ? (void) (0) : __assert_fail ("tech_pvt != ((void*)0)"
, "mod_skinny.c", 1074, __PRETTY_FUNCTION__))
;
1075
1076 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 1076, (const char*)(session)
, SWITCH_LOG_DEBUG, "DTMF ON CALL %d [%c]\n", tech_pvt->call_id, dtmf->digit);
1077
1078 return SWITCH_STATUS_SUCCESS;
1079}
1080
1081switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
1082{
1083 switch_channel_t *channel = switch_core_session_get_channel(session);
1084 private_t *tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
1085
1086 while (!(tech_pvt->read_codec.implementation && switch_rtp_ready(tech_pvt->rtp_session))) {
1087 if (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) {
1088 switch_yield(10000)switch_sleep(10000);;
1089 } else {
1090 return SWITCH_STATUS_GENERR;
1091 }
1092 }
1093
1094 tech_pvt->read_frame.datalen = 0;
1095 switch_set_flag_locked(tech_pvt, TFLAG_READING)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != ((void*)0)", "mod_skinny.c", 1095
, __PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags |= (TFLAG_READING);switch_mutex_unlock
(tech_pvt->flag_mutex);
;
1096
1097 if (switch_test_flag(tech_pvt, TFLAG_IO)((tech_pvt)->flags & TFLAG_IO)) {
1098 switch_status_t status;
1099
1100 switch_assert(tech_pvt->rtp_session != NULL)((tech_pvt->rtp_session != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->rtp_session != ((void*)0)", "mod_skinny.c", 1100
, __PRETTY_FUNCTION__))
;
1101 tech_pvt->read_frame.datalen = 0;
1102
1103
1104 while (switch_test_flag(tech_pvt, TFLAG_IO)((tech_pvt)->flags & TFLAG_IO) && tech_pvt->read_frame.datalen == 0) {
1105 tech_pvt->read_frame.flags = SFF_NONE;
1106
1107 status = switch_rtp_zerocopy_read_frame(tech_pvt->rtp_session, &tech_pvt->read_frame, flags);
1108 if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
1109 return SWITCH_STATUS_FALSE;
1110 }
1111
1112 //payload = tech_pvt->read_frame.payload;
1113
1114 if (switch_rtp_has_dtmf(tech_pvt->rtp_session)) {
1115 switch_dtmf_t dtmf = { 0 };
1116 switch_rtp_dequeue_dtmf(tech_pvt->rtp_session, &dtmf);
1117 switch_channel_queue_dtmf(channel, &dtmf);
1118 }
1119
1120
1121 if (tech_pvt->read_frame.datalen > 0) {
1122 size_t bytes = 0;
1123 int frames = 1;
1124
1125 if (!switch_test_flag((&tech_pvt->read_frame), SFF_CNG)(((&tech_pvt->read_frame))->flags & SFF_CNG)) {
1126 if ((bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_packet)) {
1127 frames = (tech_pvt->read_frame.datalen / bytes);
1128 }
1129 tech_pvt->read_frame.samples = (int) (frames * tech_pvt->read_codec.implementation->samples_per_packet);
1130 }
1131 break;
1132 }
1133 }
1134 }
1135
1136 switch_clear_flag_locked(tech_pvt, TFLAG_READING)switch_mutex_lock(tech_pvt->flag_mutex); (tech_pvt)->flags
&= ~(TFLAG_READING); switch_mutex_unlock(tech_pvt->flag_mutex
);
;
1137
1138 if (tech_pvt->read_frame.datalen == 0) {
1139 *frame = NULL((void*)0);
1140 return SWITCH_STATUS_GENERR;
1141 }
1142
1143 *frame = &tech_pvt->read_frame;
1144
1145 return SWITCH_STATUS_SUCCESS;
1146}
1147
1148switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
1149{
1150 private_t *tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
1151 //switch_frame_t *pframe;
1152 switch_status_t status = SWITCH_STATUS_SUCCESS;
1153
1154 if (!switch_test_flag(tech_pvt, TFLAG_IO)((tech_pvt)->flags & TFLAG_IO)) {
1155 return SWITCH_STATUS_FALSE;
1156 }
1157 switch_set_flag_locked(tech_pvt, TFLAG_WRITING)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != ((void*)0)", "mod_skinny.c", 1157
, __PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags |= (TFLAG_WRITING);switch_mutex_unlock
(tech_pvt->flag_mutex);
;
1158
1159 switch_rtp_write_frame(tech_pvt->rtp_session, frame);
1160
1161 switch_clear_flag_locked(tech_pvt, TFLAG_WRITING)switch_mutex_lock(tech_pvt->flag_mutex); (tech_pvt)->flags
&= ~(TFLAG_WRITING); switch_mutex_unlock(tech_pvt->flag_mutex
);
;
1162
1163 return status;
1164
1165}
1166
1167switch_status_t channel_answer_channel(switch_core_session_t *session)
1168{
1169 switch_channel_t *channel = switch_core_session_get_channel(session);
1170 private_t *tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
1171 listener_t *listener = NULL((void*)0);
1172
1173 skinny_profile_find_listener_by_device_name_and_instance(tech_pvt->profile,
1174 switch_channel_get_variable(channel, "skinny_device_name")switch_channel_get_variable_dup(channel, "skinny_device_name"
, SWITCH_TRUE, -1)
,
1175 atoi(switch_channel_get_variable(channel, "skinny_device_instance")switch_channel_get_variable_dup(channel, "skinny_device_instance"
, SWITCH_TRUE, -1)
), &listener);
1176 if (listener) {
1177 int x = 0;
1178 skinny_session_start_media(session, listener, atoi(switch_channel_get_variable(channel, "skinny_line_instance")switch_channel_get_variable_dup(channel, "skinny_line_instance"
, SWITCH_TRUE, -1)
));
1179 /* Wait for media */
1180 while(!switch_test_flag(tech_pvt, TFLAG_IO)((tech_pvt)->flags & TFLAG_IO)) {
1181 switch_cond_next();
1182 if (++x > 5000) {
1183 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 1183, (const char*)(session)
, SWITCH_LOG_WARNING, "Wait tooo long to answer %s:%s\n",
1184 switch_channel_get_variable(channel, "skinny_device_name")switch_channel_get_variable_dup(channel, "skinny_device_name"
, SWITCH_TRUE, -1)
, switch_channel_get_variable(channel, "skinny_device_instance")switch_channel_get_variable_dup(channel, "skinny_device_instance"
, SWITCH_TRUE, -1)
);
1185 return SWITCH_STATUS_FALSE;
1186 }
1187 }
1188 } else {
1189 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 1189, (const char*)(session)
, SWITCH_LOG_WARNING, "Unable to find listener to answer %s:%s\n",
1190 switch_channel_get_variable(channel, "skinny_device_name")switch_channel_get_variable_dup(channel, "skinny_device_name"
, SWITCH_TRUE, -1)
, switch_channel_get_variable(channel, "skinny_device_instance")switch_channel_get_variable_dup(channel, "skinny_device_instance"
, SWITCH_TRUE, -1)
);
1191 }
1192 return SWITCH_STATUS_SUCCESS;
1193}
1194
1195
1196switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
1197{
1198 private_t *tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
1199
1200 switch (msg->message_id) {
1201 case SWITCH_MESSAGE_INDICATE_ANSWER:
1202 switch_clear_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA)switch_mutex_lock(tech_pvt->flag_mutex); (tech_pvt)->flags
&= ~(TFLAG_EARLY_MEDIA); switch_mutex_unlock(tech_pvt->
flag_mutex);
;
1203 return channel_answer_channel(session);
1204
1205 case SWITCH_MESSAGE_INDICATE_DISPLAY:
1206 skinny_session_send_call_info_all(session);
1207 return SWITCH_STATUS_SUCCESS;
1208
1209 case SWITCH_MESSAGE_INDICATE_PROGRESS:
1210 if (!switch_test_flag(tech_pvt, TFLAG_EARLY_MEDIA)((tech_pvt)->flags & TFLAG_EARLY_MEDIA)) {
1211 /* early media */
1212 switch_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != ((void*)0)", "mod_skinny.c", 1212
, __PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags |= (TFLAG_EARLY_MEDIA);switch_mutex_unlock
(tech_pvt->flag_mutex);
;
1213 return channel_answer_channel(session);
1214 }
1215 return SWITCH_STATUS_SUCCESS;
1216
1217 default:
1218 return SWITCH_STATUS_SUCCESS;
1219
1220 }
1221
1222}
1223
1224/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines
1225 that allocate memory or you will have 1 channel with memory allocated from another channel's pool!
1226 */
1227switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
1228 switch_caller_profile_t *outbound_profile,
1229 switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause)
1230{
1231 switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1232 switch_core_session_t *nsession = NULL((void*)0);
1233 private_t *tech_pvt;
1234
1235 char *profile_name, *dest;
1236 skinny_profile_t *profile = NULL((void*)0);
1237 char *sql;
1238 char name[128];
1239 switch_channel_t *nchannel;
1240 switch_caller_profile_t *caller_profile;
1241
1242 if (!outbound_profile || zstr(outbound_profile->destination_number)_zstr(outbound_profile->destination_number)) {
1243 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 1243, ((void*)0)
, SWITCH_LOG_CRIT, "Invalid Destination\n");
1244 goto error;
1245 }
1246
1247 if (!(nsession = switch_core_session_request(skinny_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool)switch_core_session_request_uuid(skinny_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND
, flags, pool, ((void*)0))
)) {
1248 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 1248, ((void*)0)
, SWITCH_LOG_CRIT, "Error Creating Session\n");
1249 goto error;
1250 }
1251
1252 if (!(tech_pvt = (struct private_object *) switch_core_session_alloc(nsession, sizeof(*tech_pvt))switch_core_perform_session_alloc(nsession, sizeof(*tech_pvt)
, "mod_skinny.c", (const char *)__func__, 1252)
)) {
1253 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 1253, (const char*)(session)
, SWITCH_LOG_CRIT, "Error Creating Session private object\n");
1254 goto error;
1255 }
1256
1257 if(!(profile_name = switch_core_session_strdup(nsession, outbound_profile->destination_number)switch_core_perform_session_strdup(nsession, outbound_profile
->destination_number, "mod_skinny.c", (const char *)__func__
, 1257)
)) {
1258 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 1258, (const char*)(session)
, SWITCH_LOG_CRIT, "Error Creating Session Info\n");
1259 goto error;
1260 }
1261
1262 if (!(dest = strchr(profile_name, '/')(__extension__ (__builtin_constant_p ('/') && !__builtin_constant_p
(profile_name) && ('/') == '\0' ? (char *) __rawmemchr
(profile_name, '/') : __builtin_strchr (profile_name, '/')))
)) {
1263 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 1263, (const char*)(session)
, SWITCH_LOG_ERROR, "Invalid Skinny URL. Should be skinny/<profile>/<number>.\n");
1264 cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT;
1265 goto error;
1266 }
1267 *dest++ = '\0';
1268
1269 profile = skinny_find_profile(profile_name);
1270 if (!(profile = skinny_find_profile(profile_name))) {
1271 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_skinny.c", (const char *)__func__
, 1271, (const char*)(session)
, SWITCH_LOG_ERROR, "Invalid Profile %s\n", profile_name);
1272 cause = SWITCH_CAUSE_UNALLOCATED_NUMBER;
1273 goto error;
1274 }
1275
1276 snprintf(name, sizeof(name), "SKINNY/%s/%s", profile->name, dest);
1277
1278 nchannel = switch_core_session_get_channel(nsession);
1279 switch_channel_set_name(nchannel, name);
1280
1281 tech_init(tech_pvt, profile, nsession);
1282
1283 caller_profile = switch_caller_profile_clone(nsession, outbound_profile);
1284 switch_channel_set_caller_profile(nchannel, caller_profile);
1285 tech_pvt->caller_profile = caller_profile;
1286
1287 if ((sql = switch_mprintf(
1288 "INSERT INTO skinny_active_lines "
1289 "(device_name, device_instance, line_instance, channel_uuid, call_id, call_state) "
1290 "SELECT device_name, device_instance, line_instance, '%s', %d, %d "
1291 "FROM skinny_lines "
1292 "WHERE value='%s'",
1293 switch_core_session_get_uuid(nsession), tech_pvt->call_id, SKINNY_ON_HOOK, dest
1294 ))) {
1295 skinny_execute_sql(profile, sql, profile->sql_mutex);
1296 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1297 }
1298
1299 /* FIXME: ring_lines need BOND before switch_core_session_outgoing_channel() set it */
1300 if (session) {
1301 switch_channel_set_variable(switch_core_session_get_channel(session), SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(nsession))switch_channel_set_variable_var_check(switch_core_session_get_channel
(session), "signal_bond", switch_core_session_get_uuid(nsession
), SWITCH_TRUE)
;
1302 switch_channel_set_variable(nchannel, SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(session))switch_channel_set_variable_var_check(nchannel, "signal_bond"
, switch_core_session_get_uuid(session), SWITCH_TRUE)
;
1303 }
1304
1305 cause = skinny_ring_lines(tech_pvt, session);
1306
1307 if(cause != SWITCH_CAUSE_SUCCESS) {
1308 goto error;
1309 }
1310
1311 *new_session = nsession;
1312
1313 /* ?? switch_channel_mark_ring_ready(channel); */
1314
1315 if (switch_channel_get_state(nchannel) == CS_NEW) {
1316 switch_channel_set_state(nchannel, CS_INIT)switch_channel_perform_set_state(nchannel, "mod_skinny.c", (const
char *)__func__, 1316, CS_INIT)
;
1317 }
1318
1319 cause = SWITCH_CAUSE_SUCCESS;
1320 goto done;
1321
1322error:
1323 if (nsession) {
1324 switch_core_session_destroy(&nsession)switch_core_session_perform_destroy(&nsession, "mod_skinny.c"
, (const char *)__func__, 1324)
;
1325 }
1326
1327 if (pool) {
1328 *pool = NULL((void*)0);
1329 }
1330
1331
1332done:
1333
1334 if (profile) {
1335 if (cause == SWITCH_CAUSE_SUCCESS) {
1336 profile->ob_calls++;
1337 } else {
1338 profile->ob_failed_calls++;
1339 }
1340 }
1341 return cause;
1342}
1343
1344switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event)
1345{
1346 char *body = switch_event_get_body(event);
1347
1348 if (!body) {
1349 body = "";
1350 }
1351
1352 return SWITCH_STATUS_SUCCESS;
1353}
1354
1355
1356
1357switch_state_handler_table_t skinny_state_handlers = {
1358 /*.on_init */ channel_on_init,
1359 /*.on_routing */ channel_on_routing,
1360 /*.on_execute */ channel_on_execute,
1361 /*.on_hangup */ channel_on_hangup,
1362 /*.on_exchange_media */ channel_on_exchange_media,
1363 /*.on_soft_execute */ channel_on_soft_execute,
1364 /*.on_consume_media*/ NULL((void*)0),
1365 /*.on_hibernate*/ NULL((void*)0),
1366 /*.on_reset*/ NULL((void*)0),
1367 /*.on_park*/ NULL((void*)0),
1368 /*.on_reporting*/ NULL((void*)0),
1369 /*.on_destroy*/ channel_on_destroy
1370
1371};
1372
1373switch_io_routines_t skinny_io_routines = {
1374 /*.outgoing_channel */ channel_outgoing_channel,
1375 /*.read_frame */ channel_read_frame,
1376 /*.write_frame */ channel_write_frame,
1377 /*.kill_channel */ channel_kill_channel,
1378 /*.send_dtmf */ channel_send_dtmf,
1379 /*.receive_message */ channel_receive_message,
1380 /*.receive_event */ channel_receive_event
1381};
1382
1383/*****************************************************************************/
1384/* LISTENER FUNCTIONS */
1385/*****************************************************************************/
1386
1387uint8_t listener_is_ready(listener_t *listener)
1388{
1389 return globals.running
1390 && listener
1391 && listener->sock
1392 && switch_test_flag(listener, LFLAG_RUNNING)((listener)->flags & LFLAG_RUNNING)
1393 && switch_test_flag(listener->profile, PFLAG_LISTENER_READY)((listener->profile)->flags & PFLAG_LISTENER_READY)
1394 && !switch_test_flag(listener->profile, PFLAG_RESPAWN)((listener->profile)->flags & PFLAG_RESPAWN);
1395}
1396
1397static void add_listener(listener_t *listener)
1398{
1399 skinny_profile_t *profile;
1400 switch_assert(listener)((listener) ? (void) (0) : __assert_fail ("listener", "mod_skinny.c"
, 1400, __PRETTY_FUNCTION__))
;
1401 assert(listener->profile)((listener->profile) ? (void) (0) : __assert_fail ("listener->profile"
, "mod_skinny.c", 1401, __PRETTY_FUNCTION__))
;
1402 profile = listener->profile;
1403
1404 switch_mutex_lock(profile->listener_mutex);
1405 listener->next = profile->listeners;
1406 profile->listeners = listener;
1407 switch_mutex_unlock(profile->listener_mutex);
1408}
1409
1410static void remove_listener(listener_t *listener)
1411{
1412 listener_t *l, *last = NULL((void*)0);
1413 skinny_profile_t *profile;
1414 switch_assert(listener)((listener) ? (void) (0) : __assert_fail ("listener", "mod_skinny.c"
, 1414, __PRETTY_FUNCTION__))
;
1415 assert(listener->profile)((listener->profile) ? (void) (0) : __assert_fail ("listener->profile"
, "mod_skinny.c", 1415, __PRETTY_FUNCTION__))
;
1416 profile = listener->profile;
1417
1418 switch_mutex_lock(profile->listener_mutex);
1419 for (l = profile->listeners; l; l = l->next) {
1420 if (l == listener) {
1421 if (last) {
1422 last->next = l->next;
1423 } else {
1424 profile->listeners = l->next;
1425 }
1426 }
1427 last = l;
1428 }
1429 switch_mutex_unlock(profile->listener_mutex);
1430}
1431
1432
1433static void walk_listeners(skinny_listener_callback_func_t callback, void *pvt)
1434{
1435 switch_hash_index_t *hi;
1436 void *val;
1437 skinny_profile_t *profile;
1438
1439 /* walk listeners */
1440 switch_mutex_lock(globals.mutex);
1441 for (hi = switch_core_hash_first(globals.profile_hash)switch_core_hash_first_iter(globals.profile_hash, ((void*)0)); hi; hi = switch_core_hash_next(&hi)) {
1442 switch_core_hash_this(hi, NULL((void*)0), NULL((void*)0), &val);
1443 profile = (skinny_profile_t *) val;
1444
1445 profile_walk_listeners(profile, callback, pvt);
1446 }
1447 switch_mutex_unlock(globals.mutex);
1448}
1449
1450static int flush_listener_callback(void *pArg, int argc, char **argv, char **columnNames)
1451{
1452 char *profile_name = argv[0];
1453 char *value = argv[1];
1454 char *domain_name = argv[2];
1455 char *device_name = argv[3];
1456 char *device_instance = argv[4];
1457
1458 char *token = switch_mprintf("skinny/%q/%q/%q:%q", profile_name, value, device_name, device_instance);
1459 switch_core_del_registration(value, domain_name, token);
1460 switch_safe_free(token)if (token) {free(token);token=((void*)0);};
1461
1462 return 0;
1463}
1464
1465void skinny_clean_device_from_db(listener_t *listener, char *device_name)
1466{
1467 if(!zstr(device_name)_zstr(device_name)) {
1468 skinny_profile_t *profile = listener->profile;
1469 char *sql;
1470
1471 skinny_log_l(listener, SWITCH_LOG_DEBUG,switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const
char *)__func__, 1473, ((void*)0), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] "
"Clean device from DB with name '%s'\n", (_zstr(listener->
device_name) ? "_undef_" : listener->device_name), listener
->device_instance, (_zstr(listener->remote_ip) ? "_undef_"
: listener->remote_ip), listener->remote_port, device_name
)
1472 "Clean device from DB with name '%s'\n",switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const
char *)__func__, 1473, ((void*)0), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] "
"Clean device from DB with name '%s'\n", (_zstr(listener->
device_name) ? "_undef_" : listener->device_name), listener
->device_instance, (_zstr(listener->remote_ip) ? "_undef_"
: listener->remote_ip), listener->remote_port, device_name
)
1473 device_name)switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const
char *)__func__, 1473, ((void*)0), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] "
"Clean device from DB with name '%s'\n", (_zstr(listener->
device_name) ? "_undef_" : listener->device_name), listener
->device_instance, (_zstr(listener->remote_ip) ? "_undef_"
: listener->remote_ip), listener->remote_port, device_name
)
;
1474
1475 if ((sql = switch_mprintf(
1476 "DELETE FROM skinny_devices "
1477 "WHERE name='%q'",
1478 device_name))) {
1479 skinny_execute_sql(profile, sql, profile->sql_mutex);
1480 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1481 }
1482
1483 if ((sql = switch_mprintf(
1484 "DELETE FROM skinny_lines "
1485 "WHERE device_name='%q'",
1486 device_name))) {
1487 skinny_execute_sql(profile, sql, profile->sql_mutex);
1488 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1489 }
1490
1491 if ((sql = switch_mprintf(
1492 "DELETE FROM skinny_buttons "
1493 "WHERE device_name='%q'",
1494 device_name))) {
1495 skinny_execute_sql(profile, sql, profile->sql_mutex);
1496 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1497 }
1498
1499 if ((sql = switch_mprintf(
1500 "DELETE FROM skinny_active_lines "
1501 "WHERE device_name='%q'",
1502 device_name))) {
1503 skinny_execute_sql(profile, sql, profile->sql_mutex);
1504 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1505 }
1506
1507 } else {
1508 skinny_log_l_msg(listener, SWITCH_LOG_DEBUG,switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const
char *)__func__, 1509, ((void*)0), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] "
"Clean device from DB, missing device name.\n", (_zstr(listener
->device_name) ? "_undef_" : listener->device_name), listener
->device_instance, (_zstr(listener->remote_ip) ? "_undef_"
: listener->remote_ip), listener->remote_port)
1509 "Clean device from DB, missing device name.\n")switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const
char *)__func__, 1509, ((void*)0), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] "
"Clean device from DB, missing device name.\n", (_zstr(listener
->device_name) ? "_undef_" : listener->device_name), listener
->device_instance, (_zstr(listener->remote_ip) ? "_undef_"
: listener->remote_ip), listener->remote_port)
;
1510 }
1511}
1512
1513void skinny_clean_listener_from_db(listener_t *listener)
1514{
1515 if(!zstr(listener->device_name)_zstr(listener->device_name)) {
1516 skinny_profile_t *profile = listener->profile;
1517 char *sql;
1518
1519 skinny_log_l(listener, SWITCH_LOG_DEBUG,switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const
char *)__func__, 1521, ((void*)0), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] "
"Clean listener from DB with name '%s' and instance '%d'\n",
(_zstr(listener->device_name) ? "_undef_" : listener->
device_name), listener->device_instance, (_zstr(listener->
remote_ip) ? "_undef_" : listener->remote_ip), listener->
remote_port, listener->device_name, listener->device_instance
)
1520 "Clean listener from DB with name '%s' and instance '%d'\n",switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const
char *)__func__, 1521, ((void*)0), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] "
"Clean listener from DB with name '%s' and instance '%d'\n",
(_zstr(listener->device_name) ? "_undef_" : listener->
device_name), listener->device_instance, (_zstr(listener->
remote_ip) ? "_undef_" : listener->remote_ip), listener->
remote_port, listener->device_name, listener->device_instance
)
1521 listener->device_name, listener->device_instance)switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const
char *)__func__, 1521, ((void*)0), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] "
"Clean listener from DB with name '%s' and instance '%d'\n",
(_zstr(listener->device_name) ? "_undef_" : listener->
device_name), listener->device_instance, (_zstr(listener->
remote_ip) ? "_undef_" : listener->remote_ip), listener->
remote_port, listener->device_name, listener->device_instance
)
;
1522
1523 if ((sql = switch_mprintf(
1524 "DELETE FROM skinny_devices "
1525 "WHERE name='%q' and instance=%d",
1526 listener->device_name, listener->device_instance))) {
1527 skinny_execute_sql(profile, sql, profile->sql_mutex);
1528 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1529 }
1530
1531 if ((sql = switch_mprintf(
1532 "DELETE FROM skinny_lines "
1533 "WHERE device_name='%q' and device_instance=%d",
1534 listener->device_name, listener->device_instance))) {
1535 skinny_execute_sql(profile, sql, profile->sql_mutex);
1536 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1537 }
1538
1539 if ((sql = switch_mprintf(
1540 "DELETE FROM skinny_buttons "
1541 "WHERE device_name='%q' and device_instance=%d",
1542 listener->device_name, listener->device_instance))) {
1543 skinny_execute_sql(profile, sql, profile->sql_mutex);
1544 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1545 }
1546
1547 if ((sql = switch_mprintf(
1548 "DELETE FROM skinny_active_lines "
1549 "WHERE device_name='%q' and device_instance=%d",
1550 listener->device_name, listener->device_instance))) {
1551 skinny_execute_sql(profile, sql, profile->sql_mutex);
1552 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1553 }
1554
1555 } else {
1556 skinny_log_l_msg(listener, SWITCH_LOG_DEBUG,switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const
char *)__func__, 1557, ((void*)0), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] "
"Clean listener from DB, missing device name.\n", (_zstr(listener
->device_name) ? "_undef_" : listener->device_name), listener
->device_instance, (_zstr(listener->remote_ip) ? "_undef_"
: listener->remote_ip), listener->remote_port)
1557 "Clean listener from DB, missing device name.\n")switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const
char *)__func__, 1557, ((void*)0), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] "
"Clean listener from DB, missing device name.\n", (_zstr(listener
->device_name) ? "_undef_" : listener->device_name), listener
->device_instance, (_zstr(listener->remote_ip) ? "_undef_"
: listener->remote_ip), listener->remote_port)
;
1558 }
1559}
1560
1561static void flush_listener(listener_t *listener)
1562{
1563
1564 if(!zstr(listener->device_name)_zstr(listener->device_name)) {
1565 skinny_profile_t *profile = listener->profile;
1566 char *sql;
1567
1568 if ((sql = switch_mprintf(
1569 "SELECT '%q', value, '%q', '%q', '%d' "
1570 "FROM skinny_lines "
1571 "WHERE device_name='%s' AND device_instance=%d "
1572 "ORDER BY position",
1573 profile->name, profile->domain, listener->device_name, listener->device_instance,
1574 listener->device_name, listener->device_instance
1575 ))) {
1576 skinny_execute_sql_callback(profile, profile->sql_mutex, sql, flush_listener_callback, NULL((void*)0));
1577 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1578 }
1579
1580 skinny_clean_listener_from_db(listener);
1581
1582 strcpy(listener->device_name, "");
1583 }
1584}
1585
1586static int dump_device_callback(void *pArg, int argc, char **argv, char **columnNames)
1587{
1588 switch_stream_handle_t *stream = (switch_stream_handle_t *) pArg;
1589
1590 char *device_name = argv[0];
1591 char *user_id = argv[1];
1592 char *instance = argv[2];
1593 char *ip = argv[3];
1594 char *type = argv[4];
1595 char *max_streams = argv[5];
1596 char *port = argv[6];
1597 char *codec_string = argv[7];
1598 char *headset = argv[8];
1599 char *handset = argv[9];
1600 char *speaker = argv[10];
1601
1602 const char *line = "=================================================================================================";
1603 stream->write_function(stream, "%s\n", line);
1604 stream->write_function(stream, "DeviceName \t%s\n", switch_str_nil(device_name)(device_name ? device_name : ""));
1605 stream->write_function(stream, "UserId \t%s\n", user_id);
1606 stream->write_function(stream, "Instance \t%s\n", instance);
1607 stream->write_function(stream, "IP \t%s\n", ip);
1608 stream->write_function(stream, "DeviceTypeId \t%s\n", type);
1609 stream->write_function(stream, "DeviceType \t%s\n", skinny_device_type2str(atoi(type)));
1610 stream->write_function(stream, "MaxStreams \t%s\n", max_streams);
1611 stream->write_function(stream, "Port \t%s\n", port);
1612 stream->write_function(stream, "Codecs \t%s\n", codec_string);
1613 stream->write_function(stream, "HeadsetId \t%s\n", headset);
1614 if (headset) {
1615 stream->write_function(stream, "Headset \t%s\n", skinny_accessory_state2str(atoi(headset)));
1616 }
1617 stream->write_function(stream, "HandsetId \t%s\n", handset);
1618 if (handset) {
1619 stream->write_function(stream, "Handset \t%s\n", skinny_accessory_state2str(atoi(handset)));
1620 }
1621 stream->write_function(stream, "SpeakerId \t%s\n", speaker);
1622 if (speaker) {
1623 stream->write_function(stream, "Speaker \t%s\n", skinny_accessory_state2str(atoi(speaker)));
1624 }
1625 stream->write_function(stream, "%s\n", line);
1626
1627 return 0;
1628}
1629
1630switch_status_t dump_device(skinny_profile_t *profile, const char *device_name, switch_stream_handle_t *stream)
1631{
1632 char *sql;
1633 if ((sql = switch_mprintf("SELECT name, user_id, instance, ip, type, max_streams, port, codec_string, headset, handset, speaker "
1634 "FROM skinny_devices WHERE name='%s'",
1635 device_name))) {
1636 skinny_execute_sql_callback(profile, profile->sql_mutex, sql, dump_device_callback, stream);
1637 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
1638 }
1639
1640 return SWITCH_STATUS_SUCCESS;
1641}
1642
1643
1644static void close_socket(switch_socket_t **sock, skinny_profile_t *profile)
1645{
1646 switch_mutex_lock(profile->sock_mutex);
1647 if (*sock) {
1648 switch_socket_shutdown(*sock, SWITCH_SHUTDOWN_READWRITE);
1649 switch_socket_close(*sock);
1650 *sock = NULL((void*)0);
1651 }
1652 switch_mutex_unlock(profile->sock_mutex);
1653}
1654
1655switch_status_t kill_listener(listener_t *listener, void *pvt)
1656{
1657 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 1657, ((void*)0)
, SWITCH_LOG_INFO, "Killing listener %s:%d.\n",
1658 listener->device_name, listener->device_instance);
1659 switch_clear_flag(listener, LFLAG_RUNNING)(listener)->flags &= ~(LFLAG_RUNNING);
1660 close_socket(&listener->sock, listener->profile);
1661 return SWITCH_STATUS_SUCCESS;
1662}
1663
1664switch_status_t keepalive_listener(listener_t *listener, void *pvt)
1665{
1666 skinny_profile_t *profile;
1667 switch_assert(listener)((listener) ? (void) (0) : __assert_fail ("listener", "mod_skinny.c"
, 1667, __PRETTY_FUNCTION__))
;
1668 assert(listener->profile)((listener->profile) ? (void) (0) : __assert_fail ("listener->profile"
, "mod_skinny.c", 1668, __PRETTY_FUNCTION__))
;
1669 profile = listener->profile;
1670
1671 listener->expire_time = switch_epoch_time_now(NULL((void*)0))+profile->keep_alive*110/100;
1672
1673 return SWITCH_STATUS_SUCCESS;
1674}
1675
1676switch_status_t listener_digit_timeout(listener_t *listener)
1677{
1678 switch_core_session_t *session = NULL((void*)0);
1679 uint32_t line_instance = 1;
1680 uint32_t call_id = 0;
1681 switch_channel_t *channel = NULL((void*)0);
1682 private_t *tech_pvt = NULL((void*)0);
1683
1684 listener->digit_timeout_time = 0;
1685
1686 session = skinny_profile_find_session(listener->profile, listener, &line_instance, call_id);
1687 if ( !session )
1688 {
1689 line_instance = 0;
1690 session = skinny_profile_find_session(listener->profile, listener, &line_instance, 0);
1691 }
1692
1693 if ( !session)
1694 return SWITCH_STATUS_FALSE;
1695
1696 channel = switch_core_session_get_channel(session);
1697 tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
1698
1699 if (channel && tech_pvt->session) {
1700 switch_set_flag_locked(tech_pvt, TFLAG_FORCE_ROUTE)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != ((void*)0)", "mod_skinny.c", 1700
, __PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags |= (TFLAG_FORCE_ROUTE);switch_mutex_unlock
(tech_pvt->flag_mutex);
;
1701 switch_channel_set_state(channel, CS_ROUTING)switch_channel_perform_set_state(channel, "mod_skinny.c", (const
char *)__func__, 1701, CS_ROUTING)
;
1702 listener->digit_timeout_time = 0;
1703 }
1704
1705 switch_core_session_rwunlock(session);
1706
1707 return SWITCH_STATUS_SUCCESS;
1708}
1709
1710static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
1711{
1712 listener_t *listener = (listener_t *) obj;
1713 switch_status_t status;
1714 skinny_message_t *request = NULL((void*)0);
1715 skinny_profile_t *profile;
1716
1717 switch_assert(listener)((listener) ? (void) (0) : __assert_fail ("listener", "mod_skinny.c"
, 1717, __PRETTY_FUNCTION__))
;
1718 assert(listener->profile)((listener->profile) ? (void) (0) : __assert_fail ("listener->profile"
, "mod_skinny.c", 1718, __PRETTY_FUNCTION__))
;
1719 profile = listener->profile;
1720
1721 switch_mutex_lock(profile->listener_mutex);
1722 profile->listener_threads++;
1723 switch_mutex_unlock(profile->listener_mutex);
1724
1725 switch_assert(listener != NULL)((listener != ((void*)0)) ? (void) (0) : __assert_fail ("listener != ((void*)0)"
, "mod_skinny.c", 1725, __PRETTY_FUNCTION__))
;
1726
1727 if ( profile->non_blocking ) {
1728 switch_socket_opt_set(listener->sock, SWITCH_SO_TCP_NODELAY512, TRUE(!0));
1729 switch_socket_opt_set(listener->sock, SWITCH_SO_NONBLOCK8, TRUE(!0));
1730 } else {
1731 switch_socket_opt_set(listener->sock, SWITCH_SO_NONBLOCK8, FALSE0);
1732 }
1733
1734 /* 200 ms to allow reasonably fast reaction on digit timeout */
1735 switch_socket_timeout_set(listener->sock, 200000);
1736
1737 if (listener->profile->debug > 0) {
1738 skinny_log_l_msg(listener, SWITCH_LOG_DEBUG, "Connection Open\n")switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const
char *)__func__, 1738, ((void*)0), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] "
"Connection Open\n", (_zstr(listener->device_name) ? "_undef_"
: listener->device_name), listener->device_instance, (
_zstr(listener->remote_ip) ? "_undef_" : listener->remote_ip
), listener->remote_port)
;
1739 }
1740
1741 switch_set_flag_locked(listener, LFLAG_RUNNING)((listener->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("listener->flag_mutex != ((void*)0)", "mod_skinny.c", 1741
, __PRETTY_FUNCTION__));switch_mutex_lock(listener->flag_mutex
);(listener)->flags |= (LFLAG_RUNNING);switch_mutex_unlock
(listener->flag_mutex);
;
1742 keepalive_listener(listener, NULL((void*)0));
1743 add_listener(listener);
1744
1745
1746 while (listener_is_ready(listener)) {
1747 status = skinny_read_packet(listener, &request);
1748
1749 if (status != SWITCH_STATUS_SUCCESS) {
1750 switch(status) {
1751 case SWITCH_STATUS_TIMEOUT:
1752 if (listener->digit_timeout_time && listener->digit_timeout_time < switch_mono_micro_time_now()) {
1753 listener_digit_timeout(listener);
1754 continue;
1755 }
1756
1757 skinny_log_l_msg(listener, SWITCH_LOG_DEBUG, "Communication Time Out\n")switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const
char *)__func__, 1757, ((void*)0), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] "
"Communication Time Out\n", (_zstr(listener->device_name)
? "_undef_" : listener->device_name), listener->device_instance
, (_zstr(listener->remote_ip) ? "_undef_" : listener->remote_ip
), listener->remote_port)
;
1758
1759 if(listener->expire_time < switch_epoch_time_now(NULL((void*)0))) {
1760 switch_event_t *event = NULL((void*)0);
1761 /* skinny::expire event */
1762 skinny_device_event(listener, &event, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_EXPIRE"skinny::expire");
1763 switch_event_fire(&event)switch_event_fire_detailed("mod_skinny.c", (const char * )(const
char *)__func__, 1763, &event, ((void*)0))
;
1764 }
1765 break;
1766 default:
1767 skinny_log_l_msg(listener, SWITCH_LOG_DEBUG, "Communication Error\n")switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const
char *)__func__, 1767, ((void*)0), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] "
"Communication Error\n", (_zstr(listener->device_name) ? "_undef_"
: listener->device_name), listener->device_instance, (
_zstr(listener->remote_ip) ? "_undef_" : listener->remote_ip
), listener->remote_port)
;
1768 }
1769 switch_clear_flag_locked(listener, LFLAG_RUNNING)switch_mutex_lock(listener->flag_mutex); (listener)->flags
&= ~(LFLAG_RUNNING); switch_mutex_unlock(listener->flag_mutex
);
;
1770 break;
1771 }
1772 if (!listener_is_ready(listener)) {
1773 break;
1774 }
1775
1776 if (!request) {
1777 continue;
1778 }
1779
1780 if (skinny_handle_request(listener, request) != SWITCH_STATUS_SUCCESS) {
1781 switch_clear_flag_locked(listener, LFLAG_RUNNING)switch_mutex_lock(listener->flag_mutex); (listener)->flags
&= ~(LFLAG_RUNNING); switch_mutex_unlock(listener->flag_mutex
);
;
1782 switch_safe_free(request)if (request) {free(request);request=((void*)0);};
1783 break;
1784 } else {
1785 switch_safe_free(request)if (request) {free(request);request=((void*)0);};
1786 }
1787 }
1788
1789 remove_listener(listener);
1790
1791 if (listener->profile->debug > 0) {
1792 skinny_log_l_msg(listener, SWITCH_LOG_DEBUG, "Communication Complete\n")switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const
char *)__func__, 1792, ((void*)0), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] "
"Communication Complete\n", (_zstr(listener->device_name)
? "_undef_" : listener->device_name), listener->device_instance
, (_zstr(listener->remote_ip) ? "_undef_" : listener->remote_ip
), listener->remote_port)
;
1793 }
1794
1795 switch_thread_rwlock_wrlock(listener->rwlock);
1796 flush_listener(listener);
1797
1798 if (listener->sock) {
1799 close_socket(&listener->sock, profile);
1800 }
1801
1802 switch_thread_rwlock_unlock(listener->rwlock);
1803
1804 if (listener->profile->debug > 0) {
1805 skinny_log_l_msg(listener, SWITCH_LOG_DEBUG, "Communication Closed\n")switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const
char *)__func__, 1805, ((void*)0), SWITCH_LOG_DEBUG, "[%s:%d @ %s:%d] "
"Communication Closed\n", (_zstr(listener->device_name) ?
"_undef_" : listener->device_name), listener->device_instance
, (_zstr(listener->remote_ip) ? "_undef_" : listener->remote_ip
), listener->remote_port)
;
1806 }
1807
1808 if (listener->pool) {
1809 switch_memory_pool_t *pool = listener->pool;
1810 switch_core_destroy_memory_pool(&pool)switch_core_perform_destroy_memory_pool(&pool, "mod_skinny.c"
, (const char *)__func__, 1810)
;
1811 }
1812
1813 switch_mutex_lock(profile->listener_mutex);
1814 profile->listener_threads--;
1815 switch_mutex_unlock(profile->listener_mutex);
1816
1817 return NULL((void*)0);
1818}
1819
1820/* Create a thread for the socket and launch it */
1821static void launch_listener_thread(listener_t *listener)
1822{
1823 switch_thread_t *thread;
1824 switch_threadattr_t *thd_attr = NULL((void*)0);
1825
1826 switch_threadattr_create(&thd_attr, listener->pool);
1827 switch_threadattr_detach_set(thd_attr, 1);
1828 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE240 * 1024);
1829 switch_thread_create(&thread, thd_attr, listener_run, listener, listener->pool);
1830}
1831
1832static void *SWITCH_THREAD_FUNC skinny_profile_run(switch_thread_t *thread, void *obj)
1833{
1834 skinny_profile_t *profile = (skinny_profile_t *) obj;
1835 switch_status_t rv;
1836 switch_sockaddr_t *sa;
1837 switch_socket_t *inbound_socket = NULL((void*)0);
1838 listener_t *listener;
1839 switch_memory_pool_t *tmp_pool = NULL((void*)0), *listener_pool = NULL((void*)0);
1840 uint32_t errs = 0;
1841 switch_sockaddr_t *local_sa = NULL((void*)0);
1842 switch_sockaddr_t *remote_sa =NULL((void*)0);
1843
1844 if (switch_core_new_memory_pool(&tmp_pool)switch_core_perform_new_memory_pool(&tmp_pool, "mod_skinny.c"
, (const char *)__func__, 1844)
!= SWITCH_STATUS_SUCCESS) {
1845 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 1845, ((void*)0)
, SWITCH_LOG_ERROR, "OH OH no pool\n");
1846 return NULL((void*)0);
1847 }
1848
1849new_socket:
1850 while(globals.running && !profile->sock) {
1851 char *listening_ip = NULL((void*)0);
1852 switch_clear_flag_locked(profile, PFLAG_RESPAWN)switch_mutex_lock(profile->flag_mutex); (profile)->flags
&= ~(PFLAG_RESPAWN); switch_mutex_unlock(profile->flag_mutex
);
;
1853 rv = switch_sockaddr_info_get(&sa, profile->ip, SWITCH_UNSPEC0, profile->port, 0, tmp_pool);
1854 if (rv)
1855 goto fail;
1856 rv = switch_socket_create(&profile->sock, switch_sockaddr_get_family(sa), SOCK_STREAMSOCK_STREAM, SWITCH_PROTO_TCP6, tmp_pool);
1857 if (rv)
1858 goto sock_fail;
1859 rv = switch_socket_opt_set(profile->sock, SWITCH_SO_REUSEADDR16, 1);
1860 if (rv)
1861 goto sock_fail;
1862 rv = switch_socket_bind(profile->sock, sa);
1863 if (rv)
1864 goto sock_fail;
1865 rv = switch_socket_listen(profile->sock, 5);
1866 if (rv)
1867 goto sock_fail;
1868 switch_sockaddr_ip_get(&listening_ip, sa);
1869 if (!profile->ip || strcmp(listening_ip, profile->ip)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(listening_ip) && __builtin_constant_p (profile->
ip) && (__s1_len = __builtin_strlen (listening_ip), __s2_len
= __builtin_strlen (profile->ip), (!((size_t)(const void *
)((listening_ip) + 1) - (size_t)(const void *)(listening_ip) ==
1) || __s1_len >= 4) && (!((size_t)(const void *)
((profile->ip) + 1) - (size_t)(const void *)(profile->ip
) == 1) || __s2_len >= 4)) ? __builtin_strcmp (listening_ip
, profile->ip) : (__builtin_constant_p (listening_ip) &&
((size_t)(const void *)((listening_ip) + 1) - (size_t)(const
void *)(listening_ip) == 1) && (__s1_len = __builtin_strlen
(listening_ip), __s1_len < 4) ? (__builtin_constant_p (profile
->ip) && ((size_t)(const void *)((profile->ip) +
1) - (size_t)(const void *)(profile->ip) == 1) ? __builtin_strcmp
(listening_ip, profile->ip) : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (profile
->ip); int __result = (((const unsigned char *) (const char
*) (listening_ip))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (listening_ip))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (listening_ip))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (listening_ip))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(profile->ip) && ((size_t)(const void *)((profile
->ip) + 1) - (size_t)(const void *)(profile->ip) == 1) &&
(__s2_len = __builtin_strlen (profile->ip), __s2_len <
4) ? (__builtin_constant_p (listening_ip) && ((size_t
)(const void *)((listening_ip) + 1) - (size_t)(const void *)(
listening_ip) == 1) ? __builtin_strcmp (listening_ip, profile
->ip) : (- (__extension__ ({ const unsigned char *__s2 = (
const unsigned char *) (const char *) (listening_ip); int __result
= (((const unsigned char *) (const char *) (profile->ip))
[0] - __s2[0]); if (__s2_len > 0 && __result == 0)
{ __result = (((const unsigned char *) (const char *) (profile
->ip))[1] - __s2[1]); if (__s2_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
profile->ip))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (profile->ip))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(listening_ip, profile->ip)))); })
) {
1870 profile->ip = switch_core_strdup(profile->pool, listening_ip)switch_core_perform_strdup(profile->pool, listening_ip, "mod_skinny.c"
, (const char *)__func__, 1870)
;
1871 }
1872 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 1872, ((void*)0)
, SWITCH_LOG_INFO, "Socket up listening on %s:%u\n", profile->ip, profile->port);
1873
1874 break;
1875sock_fail:
1876 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 1876, ((void*)0)
, SWITCH_LOG_ERROR, "Socket Error! Could not listen on %s:%u\n", profile->ip, profile->port);
1877 if (profile->sock) {
1878 close_socket(&profile->sock, profile);
1879 profile->sock = NULL((void*)0);
1880 }
1881 switch_yield(100000)switch_sleep(100000);;
1882 }
1883
1884 switch_set_flag_locked(profile, PFLAG_LISTENER_READY)((profile->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("profile->flag_mutex != ((void*)0)", "mod_skinny.c", 1884
, __PRETTY_FUNCTION__));switch_mutex_lock(profile->flag_mutex
);(profile)->flags |= (PFLAG_LISTENER_READY);switch_mutex_unlock
(profile->flag_mutex);
;
1885
1886 while(globals.running) {
1887
1888 if (switch_core_new_memory_pool(&listener_pool)switch_core_perform_new_memory_pool(&listener_pool, "mod_skinny.c"
, (const char *)__func__, 1888)
!= SWITCH_STATUS_SUCCESS) {
1889 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 1889, ((void*)0)
, SWITCH_LOG_ERROR, "OH OH no pool\n");
1890 goto fail;
1891 }
1892
1893 assert(profile->sock)((profile->sock) ? (void) (0) : __assert_fail ("profile->sock"
, "mod_skinny.c", 1893, __PRETTY_FUNCTION__))
;
1894
1895 if ((rv = switch_socket_accept(&inbound_socket, profile->sock, listener_pool))) {
1896 if (!globals.running) {
1897 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 1897, ((void*)0)
, SWITCH_LOG_NOTICE, "Shutting Down\n");
1898 goto end;
1899 } else if (switch_test_flag(profile, PFLAG_RESPAWN)((profile)->flags & PFLAG_RESPAWN)) {
1900 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 1900, ((void*)0)
, SWITCH_LOG_NOTICE, "Respawn in progress. Waiting for socket to close.\n");
1901 while (profile->sock) {
1902 switch_cond_next();
1903 }
1904 goto new_socket;
1905 } else {
1906 /* I wish we could use strerror_r here but its not defined everywhere =/ */
1907 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 1907, ((void*)0)
, SWITCH_LOG_ERROR, "Socket Error [%s]\n", strerror(errno(*__errno_location ())));
1908 if (++errs > 100) {
1909 goto end;
1910 }
1911 }
1912 } else {
1913 errs = 0;
1914 }
1915
1916
1917 if (!(listener = switch_core_alloc(listener_pool, sizeof(*listener))switch_core_perform_alloc(listener_pool, sizeof(*listener), "mod_skinny.c"
, (const char *)__func__, 1917)
)) {
1918 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 1918, ((void*)0)
, SWITCH_LOG_ERROR, "Memory Error\n");
1919 break;
1920 }
1921
1922 switch_thread_rwlock_create(&listener->rwlock, listener_pool);
1923
1924 listener->sock = inbound_socket;
1925 listener->pool = listener_pool;
1926 listener_pool = NULL((void*)0);
1927 strcpy(listener->device_name, "");
1928 listener->profile = profile;
1929
1930 switch_mutex_init(&listener->flag_mutex, SWITCH_MUTEX_NESTED0x1, listener->pool);
1931
1932 switch_socket_addr_get(&remote_sa, SWITCH_TRUE, listener->sock);
1933 switch_get_addr(listener->remote_ip, sizeof(listener->remote_ip), remote_sa);
1934 listener->remote_port = switch_sockaddr_get_port(remote_sa);
1935
1936 switch_socket_addr_get(&local_sa, SWITCH_FALSE, listener->sock);
1937 switch_get_addr(listener->local_ip, sizeof(listener->local_ip), local_sa);
1938 listener->local_port = switch_sockaddr_get_port(local_sa);
1939
1940 launch_listener_thread(listener);
1941
1942 }
1943
1944end:
1945
1946 close_socket(&profile->sock, profile);
1947
1948 if (tmp_pool) {
1949 switch_core_destroy_memory_pool(&tmp_pool)switch_core_perform_destroy_memory_pool(&tmp_pool, "mod_skinny.c"
, (const char *)__func__, 1949)
;
1950 }
1951
1952 if (listener_pool) {
1953 switch_core_destroy_memory_pool(&listener_pool)switch_core_perform_destroy_memory_pool(&listener_pool, "mod_skinny.c"
, (const char *)__func__, 1953)
;
1954 }
1955
1956
1957fail:
1958 return NULL((void*)0);
1959}
1960
1961
1962void launch_skinny_profile_thread(skinny_profile_t *profile) {
1963 switch_thread_t *thread;
1964 switch_threadattr_t *thd_attr = NULL((void*)0);
1965
1966 switch_threadattr_create(&thd_attr, profile->pool);
1967 switch_threadattr_detach_set(thd_attr, 1);
1968 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE240 * 1024);
1969 switch_thread_create(&thread, thd_attr, skinny_profile_run, profile, profile->pool);
1970}
1971
1972/*****************************************************************************/
1973/* MODULE FUNCTIONS */
1974/*****************************************************************************/
1975switch_endpoint_interface_t *skinny_get_endpoint_interface()
1976{
1977 return skinny_endpoint_interface;
1978}
1979
1980switch_status_t skinny_profile_respawn(skinny_profile_t *profile, int force)
1981{
1982 if (force || switch_test_flag(profile, PFLAG_SHOULD_RESPAWN)((profile)->flags & PFLAG_SHOULD_RESPAWN)) {
1983 switch_clear_flag_locked(profile, PFLAG_SHOULD_RESPAWN)switch_mutex_lock(profile->flag_mutex); (profile)->flags
&= ~(PFLAG_SHOULD_RESPAWN); switch_mutex_unlock(profile->
flag_mutex);
;
1984 switch_set_flag_locked(profile, PFLAG_RESPAWN)((profile->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("profile->flag_mutex != ((void*)0)", "mod_skinny.c", 1984
, __PRETTY_FUNCTION__));switch_mutex_lock(profile->flag_mutex
);(profile)->flags |= (PFLAG_RESPAWN);switch_mutex_unlock(
profile->flag_mutex);
;
1985 switch_clear_flag_locked(profile, PFLAG_LISTENER_READY)switch_mutex_lock(profile->flag_mutex); (profile)->flags
&= ~(PFLAG_LISTENER_READY); switch_mutex_unlock(profile->
flag_mutex);
;
1986 profile_walk_listeners(profile, kill_listener, NULL((void*)0));
1987 close_socket(&profile->sock, profile);
1988 }
1989 return SWITCH_STATUS_SUCCESS;
1990}
1991
1992switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, const char *val)
1993{
1994 if (!var)
1995 return SWITCH_STATUS_FALSE;
1996
1997 if (profile->sock && !strcasecmp(var, "odbc-dsn")) {
1998 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 1998, ((void*)0)
, SWITCH_LOG_ERROR,
1999 "Skinny profile setting 'odbc-dsn' can't be changed while running\n");
2000 return SWITCH_STATUS_FALSE;
2001 }
2002
2003 if (!strcasecmp(var, "domain")) {
2004 profile->domain = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_skinny.c"
, (const char *)__func__, 2004)
;
2005 } else if (!strcasecmp(var, "ip")) {
2006 if (!profile->ip || strcmp(val, profile->ip)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(val) && __builtin_constant_p (profile->ip) &&
(__s1_len = __builtin_strlen (val), __s2_len = __builtin_strlen
(profile->ip), (!((size_t)(const void *)((val) + 1) - (size_t
)(const void *)(val) == 1) || __s1_len >= 4) && (!
((size_t)(const void *)((profile->ip) + 1) - (size_t)(const
void *)(profile->ip) == 1) || __s2_len >= 4)) ? __builtin_strcmp
(val, profile->ip) : (__builtin_constant_p (val) &&
((size_t)(const void *)((val) + 1) - (size_t)(const void *)(
val) == 1) && (__s1_len = __builtin_strlen (val), __s1_len
< 4) ? (__builtin_constant_p (profile->ip) && (
(size_t)(const void *)((profile->ip) + 1) - (size_t)(const
void *)(profile->ip) == 1) ? __builtin_strcmp (val, profile
->ip) : (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) (profile->ip); int __result
= (((const unsigned char *) (const char *) (val))[0] - __s2[
0]); if (__s1_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (val))[1] - __s2[
1]); if (__s1_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (val))[2] - __s2[
2]); if (__s1_len > 2 && __result == 0) __result =
(((const unsigned char *) (const char *) (val))[3] - __s2[3]
); } } __result; }))) : (__builtin_constant_p (profile->ip
) && ((size_t)(const void *)((profile->ip) + 1) - (
size_t)(const void *)(profile->ip) == 1) && (__s2_len
= __builtin_strlen (profile->ip), __s2_len < 4) ? (__builtin_constant_p
(val) && ((size_t)(const void *)((val) + 1) - (size_t
)(const void *)(val) == 1) ? __builtin_strcmp (val, profile->
ip) : (- (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) (val); int __result = (((const
unsigned char *) (const char *) (profile->ip))[0] - __s2[
0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (profile->ip))
[1] - __s2[1]); if (__s2_len > 1 && __result == 0)
{ __result = (((const unsigned char *) (const char *) (profile
->ip))[2] - __s2[2]); if (__s2_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (profile
->ip))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(val, profile->ip)))); })
) {
2007 profile->ip = switch_core_strdup(profile->pool, zstr(val) ? NULL : val)switch_core_perform_strdup(profile->pool, _zstr(val) ? ((void
*)0) : val, "mod_skinny.c", (const char *)__func__, 2007)
;
2008 switch_set_flag_locked(profile, PFLAG_SHOULD_RESPAWN)((profile->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("profile->flag_mutex != ((void*)0)", "mod_skinny.c", 2008
, __PRETTY_FUNCTION__));switch_mutex_lock(profile->flag_mutex
);(profile)->flags |= (PFLAG_SHOULD_RESPAWN);switch_mutex_unlock
(profile->flag_mutex);
;
2009 }
2010 } else if (!strcasecmp(var, "port")) {
2011 if (atoi(val) != profile->port) {
2012 profile->port = atoi(val);
2013 switch_set_flag_locked(profile, PFLAG_SHOULD_RESPAWN)((profile->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("profile->flag_mutex != ((void*)0)", "mod_skinny.c", 2013
, __PRETTY_FUNCTION__));switch_mutex_lock(profile->flag_mutex
);(profile)->flags |= (PFLAG_SHOULD_RESPAWN);switch_mutex_unlock
(profile->flag_mutex);
;
2014 }
2015 } else if (!strcasecmp(var, "patterns-dialplan")) {
2016 profile->patterns_dialplan = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_skinny.c"
, (const char *)__func__, 2016)
;
2017 } else if (!strcasecmp(var, "patterns-context")) {
2018 profile->patterns_context = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_skinny.c"
, (const char *)__func__, 2018)
;
2019 } else if (!strcasecmp(var, "dialplan")) {
2020 profile->dialplan = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_skinny.c"
, (const char *)__func__, 2020)
;
2021 } else if (!strcasecmp(var, "context")) {
2022 profile->context = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_skinny.c"
, (const char *)__func__, 2022)
;
2023 } else if (!strcasecmp(var, "keep-alive")) {
2024 profile->keep_alive = atoi(val);
2025 } else if (!strcasecmp(var, "digit-timeout")) {
2026 profile->digit_timeout = atoi(val);
2027 } else if (!strcasecmp(var, "date-format")) {
2028 memcpy(profile->date_format, val, 6);
2029 } else if (!strcasecmp(var, "odbc-dsn") && !zstr(val)_zstr(val)) {
2030 profile->odbc_dsn = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_skinny.c"
, (const char *)__func__, 2030)
;
2031 } else if (!strcasecmp(var, "debug")) {
2032 profile->debug = atoi(val);
2033 } else if (!strcasecmp(var, "auto-restart")) {
2034 profile->auto_restart = switch_true(val);
2035 } else if (!strcasecmp(var, "non-blocking")) {
2036 profile->non_blocking = switch_true(val);
2037 } else if (!strcasecmp(var, "ext-voicemail")) {
2038 if (!profile->ext_voicemail || strcmp(val, profile->ext_voicemail)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(val) && __builtin_constant_p (profile->ext_voicemail
) && (__s1_len = __builtin_strlen (val), __s2_len = __builtin_strlen
(profile->ext_voicemail), (!((size_t)(const void *)((val)
+ 1) - (size_t)(const void *)(val) == 1) || __s1_len >= 4
) && (!((size_t)(const void *)((profile->ext_voicemail
) + 1) - (size_t)(const void *)(profile->ext_voicemail) ==
1) || __s2_len >= 4)) ? __builtin_strcmp (val, profile->
ext_voicemail) : (__builtin_constant_p (val) && ((size_t
)(const void *)((val) + 1) - (size_t)(const void *)(val) == 1
) && (__s1_len = __builtin_strlen (val), __s1_len <
4) ? (__builtin_constant_p (profile->ext_voicemail) &&
((size_t)(const void *)((profile->ext_voicemail) + 1) - (
size_t)(const void *)(profile->ext_voicemail) == 1) ? __builtin_strcmp
(val, profile->ext_voicemail) : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (profile
->ext_voicemail); int __result = (((const unsigned char *)
(const char *) (val))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (val))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (val))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (val))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(profile->ext_voicemail) && ((size_t)(const void *
)((profile->ext_voicemail) + 1) - (size_t)(const void *)(profile
->ext_voicemail) == 1) && (__s2_len = __builtin_strlen
(profile->ext_voicemail), __s2_len < 4) ? (__builtin_constant_p
(val) && ((size_t)(const void *)((val) + 1) - (size_t
)(const void *)(val) == 1) ? __builtin_strcmp (val, profile->
ext_voicemail) : (- (__extension__ ({ const unsigned char *__s2
= (const unsigned char *) (const char *) (val); int __result
= (((const unsigned char *) (const char *) (profile->ext_voicemail
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (profile
->ext_voicemail))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (profile->ext_voicemail))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (profile->ext_voicemail))[3] - __s2
[3]); } } __result; })))) : __builtin_strcmp (val, profile->
ext_voicemail)))); })
) {
2039 profile->ext_voicemail = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_skinny.c"
, (const char *)__func__, 2039)
;
2040 }
2041 } else if (!strcasecmp(var, "ext-redial")) {
2042 if (!profile->ext_redial || strcmp(val, profile->ext_redial)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(val) && __builtin_constant_p (profile->ext_redial
) && (__s1_len = __builtin_strlen (val), __s2_len = __builtin_strlen
(profile->ext_redial), (!((size_t)(const void *)((val) + 1
) - (size_t)(const void *)(val) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((profile->ext_redial) + 1) - (size_t
)(const void *)(profile->ext_redial) == 1) || __s2_len >=
4)) ? __builtin_strcmp (val, profile->ext_redial) : (__builtin_constant_p
(val) && ((size_t)(const void *)((val) + 1) - (size_t
)(const void *)(val) == 1) && (__s1_len = __builtin_strlen
(val), __s1_len < 4) ? (__builtin_constant_p (profile->
ext_redial) && ((size_t)(const void *)((profile->ext_redial
) + 1) - (size_t)(const void *)(profile->ext_redial) == 1)
? __builtin_strcmp (val, profile->ext_redial) : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (profile->ext_redial); int __result = (((const unsigned
char *) (const char *) (val))[0] - __s2[0]); if (__s1_len >
0 && __result == 0) { __result = (((const unsigned char
*) (const char *) (val))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (val))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (val))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(profile->ext_redial) && ((size_t)(const void *)(
(profile->ext_redial) + 1) - (size_t)(const void *)(profile
->ext_redial) == 1) && (__s2_len = __builtin_strlen
(profile->ext_redial), __s2_len < 4) ? (__builtin_constant_p
(val) && ((size_t)(const void *)((val) + 1) - (size_t
)(const void *)(val) == 1) ? __builtin_strcmp (val, profile->
ext_redial) : (- (__extension__ ({ const unsigned char *__s2 =
(const unsigned char *) (const char *) (val); int __result =
(((const unsigned char *) (const char *) (profile->ext_redial
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (profile
->ext_redial))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (profile->ext_redial))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (profile->ext_redial))[3] - __s2[3
]); } } __result; })))) : __builtin_strcmp (val, profile->
ext_redial)))); })
) {
2043 profile->ext_redial = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_skinny.c"
, (const char *)__func__, 2043)
;
2044 }
2045 } else if (!strcasecmp(var, "ext-meetme")) {
2046 if (!profile->ext_meetme || strcmp(val, profile->ext_meetme)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(val) && __builtin_constant_p (profile->ext_meetme
) && (__s1_len = __builtin_strlen (val), __s2_len = __builtin_strlen
(profile->ext_meetme), (!((size_t)(const void *)((val) + 1
) - (size_t)(const void *)(val) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((profile->ext_meetme) + 1) - (size_t
)(const void *)(profile->ext_meetme) == 1) || __s2_len >=
4)) ? __builtin_strcmp (val, profile->ext_meetme) : (__builtin_constant_p
(val) && ((size_t)(const void *)((val) + 1) - (size_t
)(const void *)(val) == 1) && (__s1_len = __builtin_strlen
(val), __s1_len < 4) ? (__builtin_constant_p (profile->
ext_meetme) && ((size_t)(const void *)((profile->ext_meetme
) + 1) - (size_t)(const void *)(profile->ext_meetme) == 1)
? __builtin_strcmp (val, profile->ext_meetme) : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (profile->ext_meetme); int __result = (((const unsigned
char *) (const char *) (val))[0] - __s2[0]); if (__s1_len >
0 && __result == 0) { __result = (((const unsigned char
*) (const char *) (val))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (val))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (val))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(profile->ext_meetme) && ((size_t)(const void *)(
(profile->ext_meetme) + 1) - (size_t)(const void *)(profile
->ext_meetme) == 1) && (__s2_len = __builtin_strlen
(profile->ext_meetme), __s2_len < 4) ? (__builtin_constant_p
(val) && ((size_t)(const void *)((val) + 1) - (size_t
)(const void *)(val) == 1) ? __builtin_strcmp (val, profile->
ext_meetme) : (- (__extension__ ({ const unsigned char *__s2 =
(const unsigned char *) (const char *) (val); int __result =
(((const unsigned char *) (const char *) (profile->ext_meetme
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (profile
->ext_meetme))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (profile->ext_meetme))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (profile->ext_meetme))[3] - __s2[3
]); } } __result; })))) : __builtin_strcmp (val, profile->
ext_meetme)))); })
) {
2047 profile->ext_meetme = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_skinny.c"
, (const char *)__func__, 2047)
;
2048 }
2049 } else if (!strcasecmp(var, "ext-pickup")) {
2050 if (!profile->ext_pickup || strcmp(val, profile->ext_pickup)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(val) && __builtin_constant_p (profile->ext_pickup
) && (__s1_len = __builtin_strlen (val), __s2_len = __builtin_strlen
(profile->ext_pickup), (!((size_t)(const void *)((val) + 1
) - (size_t)(const void *)(val) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((profile->ext_pickup) + 1) - (size_t
)(const void *)(profile->ext_pickup) == 1) || __s2_len >=
4)) ? __builtin_strcmp (val, profile->ext_pickup) : (__builtin_constant_p
(val) && ((size_t)(const void *)((val) + 1) - (size_t
)(const void *)(val) == 1) && (__s1_len = __builtin_strlen
(val), __s1_len < 4) ? (__builtin_constant_p (profile->
ext_pickup) && ((size_t)(const void *)((profile->ext_pickup
) + 1) - (size_t)(const void *)(profile->ext_pickup) == 1)
? __builtin_strcmp (val, profile->ext_pickup) : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (profile->ext_pickup); int __result = (((const unsigned
char *) (const char *) (val))[0] - __s2[0]); if (__s1_len >
0 && __result == 0) { __result = (((const unsigned char
*) (const char *) (val))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (val))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (val))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(profile->ext_pickup) && ((size_t)(const void *)(
(profile->ext_pickup) + 1) - (size_t)(const void *)(profile
->ext_pickup) == 1) && (__s2_len = __builtin_strlen
(profile->ext_pickup), __s2_len < 4) ? (__builtin_constant_p
(val) && ((size_t)(const void *)((val) + 1) - (size_t
)(const void *)(val) == 1) ? __builtin_strcmp (val, profile->
ext_pickup) : (- (__extension__ ({ const unsigned char *__s2 =
(const unsigned char *) (const char *) (val); int __result =
(((const unsigned char *) (const char *) (profile->ext_pickup
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (profile
->ext_pickup))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (profile->ext_pickup))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (profile->ext_pickup))[3] - __s2[3
]); } } __result; })))) : __builtin_strcmp (val, profile->
ext_pickup)))); })
) {
2051 profile->ext_pickup = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_skinny.c"
, (const char *)__func__, 2051)
;
2052 }
2053 } else if (!strcasecmp(var, "ext-cfwdall")) {
2054 if (!profile->ext_cfwdall || strcmp(val, profile->ext_cfwdall)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(val) && __builtin_constant_p (profile->ext_cfwdall
) && (__s1_len = __builtin_strlen (val), __s2_len = __builtin_strlen
(profile->ext_cfwdall), (!((size_t)(const void *)((val) +
1) - (size_t)(const void *)(val) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((profile->ext_cfwdall) + 1) - (
size_t)(const void *)(profile->ext_cfwdall) == 1) || __s2_len
>= 4)) ? __builtin_strcmp (val, profile->ext_cfwdall) :
(__builtin_constant_p (val) && ((size_t)(const void *
)((val) + 1) - (size_t)(const void *)(val) == 1) && (
__s1_len = __builtin_strlen (val), __s1_len < 4) ? (__builtin_constant_p
(profile->ext_cfwdall) && ((size_t)(const void *)
((profile->ext_cfwdall) + 1) - (size_t)(const void *)(profile
->ext_cfwdall) == 1) ? __builtin_strcmp (val, profile->
ext_cfwdall) : (__extension__ ({ const unsigned char *__s2 = (
const unsigned char *) (const char *) (profile->ext_cfwdall
); int __result = (((const unsigned char *) (const char *) (val
))[0] - __s2[0]); if (__s1_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (val)
)[1] - __s2[1]); if (__s1_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (val)
)[2] - __s2[2]); if (__s1_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (val))[
3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (profile
->ext_cfwdall) && ((size_t)(const void *)((profile
->ext_cfwdall) + 1) - (size_t)(const void *)(profile->ext_cfwdall
) == 1) && (__s2_len = __builtin_strlen (profile->
ext_cfwdall), __s2_len < 4) ? (__builtin_constant_p (val) &&
((size_t)(const void *)((val) + 1) - (size_t)(const void *)(
val) == 1) ? __builtin_strcmp (val, profile->ext_cfwdall) :
(- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (val); int __result = (((const unsigned
char *) (const char *) (profile->ext_cfwdall))[0] - __s2[
0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (profile->ext_cfwdall
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (profile
->ext_cfwdall))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (profile->ext_cfwdall))[3] - __s2[3]); } } __result; }
)))) : __builtin_strcmp (val, profile->ext_cfwdall)))); })
) {
2055 profile->ext_cfwdall = switch_core_strdup(profile->pool, val)switch_core_perform_strdup(profile->pool, val, "mod_skinny.c"
, (const char *)__func__, 2055)
;
2056 }
2057 } else {
2058 return SWITCH_STATUS_FALSE;
2059 }
2060
2061 return SWITCH_STATUS_SUCCESS;
2062}
2063
2064void profile_walk_listeners(skinny_profile_t *profile, skinny_listener_callback_func_t callback, void *pvt)
2065{
2066 listener_t *l;
2067
2068 switch_mutex_lock(profile->listener_mutex);
2069 for (l = profile->listeners; l; l = l->next) {
2070 callback(l, pvt);
2071 }
2072 switch_mutex_unlock(profile->listener_mutex);
2073}
2074
2075static switch_status_t load_skinny_config(void)
2076{
2077 char *cf = "skinny.conf";
2078 switch_xml_t xcfg, xml, xprofiles, xprofile;
2079 switch_cache_db_handle_t *dbh = NULL((void*)0);
2080
2081 if (!(xml = switch_xml_open_cfg(cf, &xcfg, NULL((void*)0)))) {
2082 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2082, ((void*)0)
, SWITCH_LOG_ERROR, "Open of %s failed\n", cf);
2083 return SWITCH_STATUS_TERM;
2084 }
2085
2086 switch_mutex_lock(globals.mutex);
2087 if ((xprofiles = switch_xml_child(xcfg, "profiles"))) {
2088 for (xprofile = switch_xml_child(xprofiles, "profile"); xprofile; xprofile = xprofile->next) {
2089 char *profile_name = (char *) switch_xml_attr_soft(xprofile, "name");
2090 switch_xml_t xsettings, xdevice_types, xsoft_key_set_sets;
2091 if (zstr(profile_name)_zstr(profile_name)) {
2092 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2092, ((void*)0)
, SWITCH_LOG_ERROR,
2093 "<profile> is missing name attribute\n");
2094 continue;
2095 }
2096 if ((xsettings = switch_xml_child(xprofile, "settings"))) {
2097 switch_memory_pool_t *profile_pool = NULL((void*)0);
2098 char dbname[256];
2099 skinny_profile_t *profile = NULL((void*)0);
2100 switch_xml_t param;
2101
2102 if (switch_core_new_memory_pool(&profile_pool)switch_core_perform_new_memory_pool(&profile_pool, "mod_skinny.c"
, (const char *)__func__, 2102)
!= SWITCH_STATUS_SUCCESS) {
2103 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2103, ((void*)0)
, SWITCH_LOG_ERROR, "OH OH no pool\n");
2104 return SWITCH_STATUS_TERM;
2105 }
2106 profile = switch_core_alloc(profile_pool, sizeof(skinny_profile_t))switch_core_perform_alloc(profile_pool, sizeof(skinny_profile_t
), "mod_skinny.c", (const char *)__func__, 2106)
;
2107 profile->pool = profile_pool;
2108 profile->name = switch_core_strdup(profile->pool, profile_name)switch_core_perform_strdup(profile->pool, profile_name, "mod_skinny.c"
, (const char *)__func__, 2108)
;
2109 profile->auto_restart = SWITCH_TRUE;
2110 profile->non_blocking = SWITCH_FALSE;
2111 profile->digit_timeout = 10000; /* 10 seconds */
2112 switch_mutex_init(&profile->sql_mutex, SWITCH_MUTEX_NESTED0x1, profile->pool);
2113 switch_mutex_init(&profile->listener_mutex, SWITCH_MUTEX_NESTED0x1, profile->pool);
2114 switch_mutex_init(&profile->sock_mutex, SWITCH_MUTEX_NESTED0x1, profile->pool);
2115 switch_mutex_init(&profile->flag_mutex, SWITCH_MUTEX_NESTED0x1, profile->pool);
2116
2117 for (param = switch_xml_child(xsettings, "param"); param; param = param->next) {
2118 char *var = (char *) switch_xml_attr_soft(param, "name");
2119 char *val = (char *) switch_xml_attr_soft(param, "value");
2120
2121 if (skinny_profile_set(profile, var, val) != SWITCH_STATUS_SUCCESS) {
2122 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2122, ((void*)0)
, SWITCH_LOG_WARNING,
2123 "Unable to set skinny setting '%s'. Does it exists?\n", var);
2124 }
2125 } /* param */
2126
2127 if (!profile->dialplan) {
2128 skinny_profile_set(profile, "dialplan","XML");
2129 }
2130
2131 if (!profile->context) {
2132 skinny_profile_set(profile, "context","default");
2133 }
2134
2135 if (!profile->patterns_dialplan) {
2136 skinny_profile_set(profile, "patterns-dialplan","XML");
2137 }
2138
2139 if (!profile->patterns_context) {
2140 skinny_profile_set(profile, "patterns-context","skinny-patterns");
2141 }
2142
2143 if (!profile->ext_voicemail) {
2144 skinny_profile_set(profile, "ext-voicemail", "vmain");
2145 }
2146
2147 if (!profile->ext_redial) {
2148 skinny_profile_set(profile, "ext-redial", "redial");
2149 }
2150
2151 if (!profile->ext_meetme) {
2152 skinny_profile_set(profile, "ext-meetme", "conference");
2153 }
2154
2155 if (!profile->ext_pickup) {
2156 skinny_profile_set(profile, "ext-pickup", "pickup");
2157 }
2158
2159 if (!profile->ext_cfwdall) {
2160 skinny_profile_set(profile, "ext-pickup", "cfwdall");
2161 }
2162
2163 if (profile->port == 0) {
2164 profile->port = 2000;
2165 }
2166
2167 /* Soft Key Set Sets */
2168 switch_core_hash_init(&profile->soft_key_set_sets_hash)switch_core_hash_init_case(&profile->soft_key_set_sets_hash
, SWITCH_TRUE)
;
2169 if ((xsoft_key_set_sets = switch_xml_child(xprofile, "soft-key-set-sets"))) {
2170 switch_xml_t xsoft_key_set_set;
2171 for (xsoft_key_set_set = switch_xml_child(xsoft_key_set_sets, "soft-key-set-set"); xsoft_key_set_set; xsoft_key_set_set = xsoft_key_set_set->next) {
2172 char *soft_key_set_set_name = (char *) switch_xml_attr_soft(xsoft_key_set_set, "name");
2173 if (soft_key_set_set_name) {
2174 switch_xml_t xsoft_key_set;
2175 skinny_message_t *message;
2176 message = switch_core_alloc(profile->pool, 12+sizeof(message->data.soft_key_set))switch_core_perform_alloc(profile->pool, 12+sizeof(message
->data.soft_key_set), "mod_skinny.c", (const char *)__func__
, 2176)
;
2177 message->type = SOFT_KEY_SET_RES_MESSAGE0x0109;
2178 message->length = 4 + sizeof(message->data.soft_key_set);
2179 message->data.soft_key_set.soft_key_set_offset = 0;
2180 message->data.soft_key_set.soft_key_set_count = 11;
2181 message->data.soft_key_set.total_soft_key_set_count = 11;
2182 for (xsoft_key_set = switch_xml_child(xsoft_key_set_set, "soft-key-set"); xsoft_key_set; xsoft_key_set = xsoft_key_set->next) {
2183 uint32_t soft_key_set_id;
2184 if ((soft_key_set_id = skinny_str2soft_key_set(switch_xml_attr_soft(xsoft_key_set, "name"))) != -1) {
2185 char *val =switch_core_strdup(profile->pool, switch_xml_attr_soft(xsoft_key_set, "value"))switch_core_perform_strdup(profile->pool, switch_xml_attr_soft
(xsoft_key_set, "value"), "mod_skinny.c", (const char *)__func__
, 2185)
;
2186 size_t string_len = strlen(val);
2187 size_t string_pos, start = 0;
2188 int field_no = 0;
2189 if (zstr(val)_zstr(val)) {
2190 continue;
2191 }
2192 if (soft_key_set_id > 15) {
2193 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2193, ((void*)0)
, SWITCH_LOG_WARNING,
2194 "soft-key-set name '%s' is greater than 15 in soft-key-set-set '%s' in profile %s.\n",
2195 switch_xml_attr_soft(xsoft_key_set, "name"), soft_key_set_set_name, profile->name);
2196 continue;
2197 }
2198 for (string_pos = 0; string_pos <= string_len; string_pos++) {
2199 if ((val[string_pos] == ',') || (string_pos == string_len)) {
2200 val[string_pos] = '\0';
2201 if (field_no > 15) {
2202 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2202, ((void*)0)
, SWITCH_LOG_WARNING,
2203 "soft-key-set name '%s' is limited to 16 buttons in soft-key-set-set '%s' in profile %s.\n",
2204 switch_xml_attr_soft(xsoft_key_set, "name"), soft_key_set_set_name, profile->name);
2205 break;
2206 }
2207 message->data.soft_key_set.soft_key_set[soft_key_set_id].soft_key_template_index[field_no++] = skinny_str2soft_key_event(&val[start]);
2208 start = string_pos+1;
2209 }
2210 }
2211 } else {
2212 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2212, ((void*)0)
, SWITCH_LOG_WARNING,
2213 "Unknown soft-key-set name '%s' in soft-key-set-set '%s' in profile %s.\n",
2214 switch_xml_attr_soft(xsoft_key_set, "name"), soft_key_set_set_name, profile->name);
2215 }
2216 } /* soft-key-set */
2217 switch_core_hash_insert(profile->soft_key_set_sets_hash, soft_key_set_set_name, message)switch_core_hash_insert_destructor(profile->soft_key_set_sets_hash
, soft_key_set_set_name, message, ((void*)0))
;
2218 } else {
2219 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2219, ((void*)0)
, SWITCH_LOG_WARNING,
2220 "<soft-key-set-set> is missing a name attribute in profile %s.\n", profile->name);
2221 }
2222 } /* soft-key-set-set */
2223 } else {
2224 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2224, ((void*)0)
, SWITCH_LOG_WARNING,
2225 "<soft-key-set-sets> is missing in profile %s.\n", profile->name);
2226 } /* soft-key-set-sets */
2227 if (!switch_core_hash_find(profile->soft_key_set_sets_hash, "default")) {
2228 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2228, ((void*)0)
, SWITCH_LOG_ERROR,
2229 "Profile %s doesn't have a default <soft-key-set-set>. Profile ignored.\n", profile->name);
2230 switch_core_destroy_memory_pool(&profile_pool)switch_core_perform_destroy_memory_pool(&profile_pool, "mod_skinny.c"
, (const char *)__func__, 2230)
;
2231 continue;
2232 }
2233
2234
2235 /* Device types */
2236 switch_core_hash_init(&profile->device_type_params_hash)switch_core_hash_init_case(&profile->device_type_params_hash
, SWITCH_TRUE)
;
2237 if ((xdevice_types = switch_xml_child(xprofile, "device-types"))) {
2238 switch_xml_t xdevice_type;
2239 for (xdevice_type = switch_xml_child(xdevice_types, "device-type"); xdevice_type; xdevice_type = xdevice_type->next) {
2240 uint32_t id = skinny_str2device_type(switch_xml_attr_soft(xdevice_type, "id"));
2241 if (id != 0) {
2242 char *id_str = switch_mprintf("%d", id);
2243 skinny_device_type_params_t *params = switch_core_alloc(profile->pool, sizeof(skinny_device_type_params_t))switch_core_perform_alloc(profile->pool, sizeof(skinny_device_type_params_t
), "mod_skinny.c", (const char *)__func__, 2243)
;
2244 for (param = switch_xml_child(xdevice_type, "param"); param; param = param->next) {
2245 char *var = (char *) switch_xml_attr_soft(param, "name");
2246 char *val = (char *) switch_xml_attr_soft(param, "value");
2247
2248 if (!strcasecmp(var, "firmware-version")) {
2249 strncpy(params->firmware_version, val, 16)__builtin_strncpy (params->firmware_version, val, 16);
2250 }
2251 } /* param */
2252 switch_core_hash_insert(profile->device_type_params_hash, id_str, params)switch_core_hash_insert_destructor(profile->device_type_params_hash
, id_str, params, ((void*)0))
;
2253 switch_safe_free(id_str)if (id_str) {free(id_str);id_str=((void*)0);};
2254 } else {
2255 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2255, ((void*)0)
, SWITCH_LOG_WARNING,
2256 "Unknow device type %s in profile %s.\n", switch_xml_attr_soft(xdevice_type, "id"), profile->name);
2257 }
2258 }
2259 }
2260
2261 /* Database */
2262 switch_snprintf(dbname, sizeof(dbname), "skinny_%s", profile->name);
2263 profile->dbname = switch_core_strdup(profile->pool, dbname)switch_core_perform_strdup(profile->pool, dbname, "mod_skinny.c"
, (const char *)__func__, 2263)
;
2264
2265
2266
2267
2268 if ((dbh = skinny_get_db_handle(profile))) {
2269 switch_cache_db_test_reactive(dbh, "select count(*) from skinny_devices", NULL((void*)0), devices_sql);
2270 switch_cache_db_test_reactive(dbh, "select count(*) from skinny_lines", NULL((void*)0), lines_sql);
2271 switch_cache_db_test_reactive(dbh, "select count(*) from skinny_buttons", NULL((void*)0), buttons_sql);
2272 switch_cache_db_test_reactive(dbh, "select count(*) from skinny_active_lines", NULL((void*)0), active_lines_sql);
2273 switch_cache_db_release_db_handle(&dbh);
2274 }
2275
2276 skinny_profile_respawn(profile, 0);
2277
2278 /* Register profile */
2279 switch_mutex_lock(globals.mutex);
2280 switch_core_hash_insert(globals.profile_hash, profile->name, profile)switch_core_hash_insert_destructor(globals.profile_hash, profile
->name, profile, ((void*)0))
;
2281 switch_mutex_unlock(globals.mutex);
2282 profile = NULL((void*)0);
2283 } else {
2284 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2284, ((void*)0)
, SWITCH_LOG_ERROR,
2285 "Settings are missing from profile %s.\n", profile_name);
2286 } /* settings */
2287 } /* profile */
2288 }
2289 switch_xml_free(xml);
2290 switch_mutex_unlock(globals.mutex);
2291
2292 return SWITCH_STATUS_SUCCESS;
2293}
2294
2295static void skinny_user_to_device_event_handler(switch_event_t *event)
2296{
2297 char *profile_name = switch_event_get_header_nil(event, "Skinny-Profile-Name")(switch_event_get_header_idx(event, "Skinny-Profile-Name", -1
) ? switch_event_get_header_idx(event, "Skinny-Profile-Name",
-1) : "")
;
2298 skinny_profile_t *profile;
2299
2300 if ((profile = skinny_find_profile(profile_name))) {
2301 char *device_name = switch_event_get_header_nil(event, "Skinny-Device-Name")(switch_event_get_header_idx(event, "Skinny-Device-Name", -1)
? switch_event_get_header_idx(event, "Skinny-Device-Name", -
1) : "")
;
2302 uint32_t device_instance = atoi(switch_event_get_header_nil(event, "Skinny-Station-Instance")(switch_event_get_header_idx(event, "Skinny-Station-Instance"
, -1) ? switch_event_get_header_idx(event, "Skinny-Station-Instance"
, -1) : "")
);
2303 listener_t *listener = NULL((void*)0);
2304 skinny_profile_find_listener_by_device_name_and_instance(profile, device_name, device_instance, &listener);
2305 if(listener) {
2306 uint32_t message_type = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Message-Id")(switch_event_get_header_idx(event, "Skinny-UserToDevice-Message-Id"
, -1) ? switch_event_get_header_idx(event, "Skinny-UserToDevice-Message-Id"
, -1) : "")
);
2307 uint32_t application_id = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Application-Id")(switch_event_get_header_idx(event, "Skinny-UserToDevice-Application-Id"
, -1) ? switch_event_get_header_idx(event, "Skinny-UserToDevice-Application-Id"
, -1) : "")
);
2308 uint32_t line_instance = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Line-Instance")(switch_event_get_header_idx(event, "Skinny-UserToDevice-Line-Instance"
, -1) ? switch_event_get_header_idx(event, "Skinny-UserToDevice-Line-Instance"
, -1) : "")
);
2309 uint32_t call_id = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Call-Id")(switch_event_get_header_idx(event, "Skinny-UserToDevice-Call-Id"
, -1) ? switch_event_get_header_idx(event, "Skinny-UserToDevice-Call-Id"
, -1) : "")
);
2310 uint32_t transaction_id = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Transaction-Id")(switch_event_get_header_idx(event, "Skinny-UserToDevice-Transaction-Id"
, -1) ? switch_event_get_header_idx(event, "Skinny-UserToDevice-Transaction-Id"
, -1) : "")
);
2311 uint32_t data_length = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Data-Length")(switch_event_get_header_idx(event, "Skinny-UserToDevice-Data-Length"
, -1) ? switch_event_get_header_idx(event, "Skinny-UserToDevice-Data-Length"
, -1) : "")
)
;
Value stored to 'data_length' during its initialization is never read
2312 uint32_t sequence_flag = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Sequence-Flag")(switch_event_get_header_idx(event, "Skinny-UserToDevice-Sequence-Flag"
, -1) ? switch_event_get_header_idx(event, "Skinny-UserToDevice-Sequence-Flag"
, -1) : "")
);
2313 uint32_t display_priority = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Display-Priority")(switch_event_get_header_idx(event, "Skinny-UserToDevice-Display-Priority"
, -1) ? switch_event_get_header_idx(event, "Skinny-UserToDevice-Display-Priority"
, -1) : "")
);
2314 uint32_t conference_id = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Conference-Id")(switch_event_get_header_idx(event, "Skinny-UserToDevice-Conference-Id"
, -1) ? switch_event_get_header_idx(event, "Skinny-UserToDevice-Conference-Id"
, -1) : "")
);
2315 uint32_t app_instance_id = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-App-Instance-Id")(switch_event_get_header_idx(event, "Skinny-UserToDevice-App-Instance-Id"
, -1) ? switch_event_get_header_idx(event, "Skinny-UserToDevice-App-Instance-Id"
, -1) : "")
);
2316 uint32_t routing_id = atoi(switch_event_get_header_nil(event, "Skinny-UserToDevice-Routing-Id")(switch_event_get_header_idx(event, "Skinny-UserToDevice-Routing-Id"
, -1) ? switch_event_get_header_idx(event, "Skinny-UserToDevice-Routing-Id"
, -1) : "")
);
2317 char *data = switch_event_get_body(event);
2318 if (message_type == 0) {
2319 message_type = skinny_str2message_type(switch_event_get_header_nil(event, "Skinny-UserToDevice-Message-Id-String")(switch_event_get_header_idx(event, "Skinny-UserToDevice-Message-Id-String"
, -1) ? switch_event_get_header_idx(event, "Skinny-UserToDevice-Message-Id-String"
, -1) : "")
);
2320 }
2321 switch(message_type) {
2322 case USER_TO_DEVICE_DATA_MESSAGE0x011E:
2323 data_length = strlen(data); /* we ignore data_length sent */
2324 send_data(listener, message_type,perform_send_data(listener, "mod_skinny.c", (const char *)__func__
, 2326, message_type, application_id, line_instance, call_id,
transaction_id, data_length, data)
2325 application_id, line_instance, call_id, transaction_id, data_length,perform_send_data(listener, "mod_skinny.c", (const char *)__func__
, 2326, message_type, application_id, line_instance, call_id,
transaction_id, data_length, data)
2326 data)perform_send_data(listener, "mod_skinny.c", (const char *)__func__
, 2326, message_type, application_id, line_instance, call_id,
transaction_id, data_length, data)
;
2327 case USER_TO_DEVICE_DATA_VERSION1_MESSAGE0x013F:
2328 data_length = strlen(data); /* we ignore data_length sent */
2329 send_extended_data(listener, message_type,perform_send_extended_data(listener, "mod_skinny.c", (const char
*)__func__, 2332, message_type, application_id, line_instance
, call_id, transaction_id, data_length, sequence_flag, display_priority
, conference_id, app_instance_id, routing_id, data)
2330 application_id, line_instance, call_id, transaction_id, data_length,perform_send_extended_data(listener, "mod_skinny.c", (const char
*)__func__, 2332, message_type, application_id, line_instance
, call_id, transaction_id, data_length, sequence_flag, display_priority
, conference_id, app_instance_id, routing_id, data)
2331 sequence_flag, display_priority, conference_id, app_instance_id, routing_id,perform_send_extended_data(listener, "mod_skinny.c", (const char
*)__func__, 2332, message_type, application_id, line_instance
, call_id, transaction_id, data_length, sequence_flag, display_priority
, conference_id, app_instance_id, routing_id, data)
2332 data)perform_send_extended_data(listener, "mod_skinny.c", (const char
*)__func__, 2332, message_type, application_id, line_instance
, call_id, transaction_id, data_length, sequence_flag, display_priority
, conference_id, app_instance_id, routing_id, data)
;
2333 break;
2334 default:
2335 skinny_log_l(listener, SWITCH_LOG_WARNING, "Incorrect message type %s (%d).\n", skinny_message_type2str(message_type), message_type)switch_log_printf(SWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const
char *)__func__, 2335, ((void*)0), SWITCH_LOG_WARNING, "[%s:%d @ %s:%d] "
"Incorrect message type %s (%d).\n", (_zstr(listener->device_name
) ? "_undef_" : listener->device_name), listener->device_instance
, (_zstr(listener->remote_ip) ? "_undef_" : listener->remote_ip
), listener->remote_port, skinny_message_type2str(message_type
), message_type)
;
2336 }
2337 } else {
2338 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2338, ((void*)0)
, SWITCH_LOG_WARNING,
2339 "Device %s:%d in profile '%s' not found.\n", device_name, device_instance, profile_name);
2340 }
2341 } else {
2342 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2342, ((void*)0)
, SWITCH_LOG_WARNING,
2343 "Profile '%s' not found.\n", profile_name);
2344 }
2345}
2346
2347static void skinny_call_state_event_handler(switch_event_t *event)
2348{
2349 char *subclass;
2350
2351 if ((subclass = switch_event_get_header_nil(event, "Event-Subclass")(switch_event_get_header_idx(event, "Event-Subclass", -1) ? switch_event_get_header_idx
(event, "Event-Subclass", -1) : "")
) && !strcasecmp(subclass, SKINNY_EVENT_CALL_STATE"skinny::call_state")) {
2352 char *profile_name = switch_event_get_header_nil(event, "Skinny-Profile-Name")(switch_event_get_header_idx(event, "Skinny-Profile-Name", -1
) ? switch_event_get_header_idx(event, "Skinny-Profile-Name",
-1) : "")
;
2353 char *device_name = switch_event_get_header_nil(event, "Skinny-Device-Name")(switch_event_get_header_idx(event, "Skinny-Device-Name", -1)
? switch_event_get_header_idx(event, "Skinny-Device-Name", -
1) : "")
;
2354 uint32_t device_instance = atoi(switch_event_get_header_nil(event, "Skinny-Station-Instance")(switch_event_get_header_idx(event, "Skinny-Station-Instance"
, -1) ? switch_event_get_header_idx(event, "Skinny-Station-Instance"
, -1) : "")
);
2355 uint32_t line_instance = atoi(switch_event_get_header_nil(event, "Skinny-Line-Instance")(switch_event_get_header_idx(event, "Skinny-Line-Instance", -
1) ? switch_event_get_header_idx(event, "Skinny-Line-Instance"
, -1) : "")
);
2356 uint32_t call_id = atoi(switch_event_get_header_nil(event, "Skinny-Call-Id")(switch_event_get_header_idx(event, "Skinny-Call-Id", -1) ? switch_event_get_header_idx
(event, "Skinny-Call-Id", -1) : "")
);
2357 uint32_t call_state = atoi(switch_event_get_header_nil(event, "Skinny-Call-State")(switch_event_get_header_idx(event, "Skinny-Call-State", -1) ?
switch_event_get_header_idx(event, "Skinny-Call-State", -1) :
"")
);
2358 skinny_profile_t *profile;
2359 listener_t *listener = NULL((void*)0);
2360 char *line_instance_condition, *call_id_condition;
2361 char *sql;
2362
2363 if ((profile = skinny_find_profile(profile_name))) {
2364 skinny_profile_find_listener_by_device_name_and_instance(profile, device_name, device_instance, &listener);
2365 if(listener) {
2366 if(line_instance > 0) {
2367 line_instance_condition = switch_mprintf("line_instance=%d", line_instance);
2368 } else {
2369 line_instance_condition = switch_mprintf("1=1");
2370 }
2371 switch_assert(line_instance_condition)((line_instance_condition) ? (void) (0) : __assert_fail ("line_instance_condition"
, "mod_skinny.c", 2371, __PRETTY_FUNCTION__))
;
2372 if(call_id > 0) {
2373 call_id_condition = switch_mprintf("call_id=%d", call_id);
2374 } else {
2375 call_id_condition = switch_mprintf("1=1");
2376 }
2377 switch_assert(call_id_condition)((call_id_condition) ? (void) (0) : __assert_fail ("call_id_condition"
, "mod_skinny.c", 2377, __PRETTY_FUNCTION__))
;
2378
2379 if ((sql = switch_mprintf(
2380 "UPDATE skinny_active_lines "
2381 "SET call_state=%d "
2382 "WHERE device_name='%q' AND device_instance=%d "
2383 "AND %q AND %q",
2384 call_state,
2385 listener->device_name, listener->device_instance,
2386 line_instance_condition, call_id_condition
2387 ))) {
2388 skinny_execute_sql(listener->profile, sql, listener->profile->sql_mutex);
2389 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
2390 }
2391 switch_safe_free(line_instance_condition)if (line_instance_condition) {free(line_instance_condition);line_instance_condition
=((void*)0);}
;
2392 switch_safe_free(call_id_condition)if (call_id_condition) {free(call_id_condition);call_id_condition
=((void*)0);}
;
2393 } else {
2394 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2394, ((void*)0)
, SWITCH_LOG_WARNING,
2395 "Device %s:%d in profile '%s' not found.\n", device_name, device_instance, profile_name);
2396 }
2397 } else {
2398 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2398, ((void*)0)
, SWITCH_LOG_WARNING,
2399 "Profile '%s' not found.\n", profile_name);
2400 }
2401 }
2402}
2403
2404struct skinny_message_waiting_event_handler_helper {
2405 skinny_profile_t *profile;
2406 switch_bool_t yn;
2407 int total_new_messages;
2408 int total_saved_messages;
2409 int total_new_urgent_messages;
2410 int total_saved_urgent_messages;
2411};
2412
2413int skinny_message_waiting_event_handler_callback(void *pArg, int argc, char **argv, char **columnNames)
2414{
2415 char *device_name = argv[0];
2416 uint32_t device_instance = atoi(argv[1]);
2417
2418 struct skinny_message_waiting_event_handler_helper *helper = pArg;
2419 listener_t *listener = NULL((void*)0);
2420
2421 skinny_profile_find_listener_by_device_name_and_instance(helper->profile,
2422 device_name, device_instance, &listener);
2423
2424 if (listener) {
2425 if (helper->yn == SWITCH_TRUE) {
2426 char buffer[32];
2427 char *label;
2428 send_set_lamp(listener, SKINNY_BUTTON_VOICEMAIL, 0, SKINNY_LAMP_ON)perform_send_set_lamp(listener, "mod_skinny.c", (const char *
)__func__, 2428, SKINNY_BUTTON_VOICEMAIL, 0, SKINNY_LAMP_ON)
;
2429
2430 label = skinny_textid2raw(SKINNY_TEXTID_YOU_HAVE_VOICEMAIL)(SKINNY_TEXTID_YOU_HAVE_VOICEMAIL > 0 ? switch_mprintf("\200%c"
, SKINNY_TEXTID_YOU_HAVE_VOICEMAIL) : switch_mprintf(""))
;
2431 sprintf(buffer, "%s: (%d/%d urgents)", label, helper->total_new_messages, helper->total_new_urgent_messages);
2432 switch_safe_free(label)if (label) {free(label);label=((void*)0);};
2433
2434 send_display_pri_notify(listener, 5, 10, buffer)perform_send_display_pri_notify(listener, "mod_skinny.c", (const
char *)__func__, 2434, 5, 10, buffer)
;
2435 } else {
2436 send_set_lamp(listener, SKINNY_BUTTON_VOICEMAIL, 0, SKINNY_LAMP_OFF)perform_send_set_lamp(listener, "mod_skinny.c", (const char *
)__func__, 2436, SKINNY_BUTTON_VOICEMAIL, 0, SKINNY_LAMP_OFF)
;
2437 send_clear_prompt_status(listener, 0, 0)perform_send_clear_prompt_status(listener, "mod_skinny.c", (const
char *)__func__, 2437, 0, 0)
;
2438 }
2439 }
2440 return 0;
2441}
2442
2443static void skinny_message_waiting_event_handler(switch_event_t *event)
2444{
2445 char *account, *dup_account, *yn, *host, *user, *count_str;
2446 char *pname = NULL((void*)0);
2447 skinny_profile_t *profile = NULL((void*)0);
2448 char *sql;
2449
2450 if (!(account = switch_event_get_header(event, "mwi-message-account")switch_event_get_header_idx(event, "mwi-message-account", -1))) {
2451 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2451, ((void*)0)
, SWITCH_LOG_ERROR, "Missing required Header 'MWI-Message-Account'\n");
2452 return;
2453 }
2454
2455 if (!strncmp("sip:", account, 4)(__extension__ (__builtin_constant_p (4) && ((__builtin_constant_p
("sip:") && strlen ("sip:") < ((size_t) (4))) || (
__builtin_constant_p (account) && strlen (account) <
((size_t) (4)))) ? __extension__ ({ size_t __s1_len, __s2_len
; (__builtin_constant_p ("sip:") && __builtin_constant_p
(account) && (__s1_len = __builtin_strlen ("sip:"), __s2_len
= __builtin_strlen (account), (!((size_t)(const void *)(("sip:"
) + 1) - (size_t)(const void *)("sip:") == 1) || __s1_len >=
4) && (!((size_t)(const void *)((account) + 1) - (size_t
)(const void *)(account) == 1) || __s2_len >= 4)) ? __builtin_strcmp
("sip:", account) : (__builtin_constant_p ("sip:") &&
((size_t)(const void *)(("sip:") + 1) - (size_t)(const void *
)("sip:") == 1) && (__s1_len = __builtin_strlen ("sip:"
), __s1_len < 4) ? (__builtin_constant_p (account) &&
((size_t)(const void *)((account) + 1) - (size_t)(const void
*)(account) == 1) ? __builtin_strcmp ("sip:", account) : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (account); int __result = (((const unsigned char *) (
const char *) ("sip:"))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ("sip:"))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ("sip:"))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ("sip:"))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(account) && ((size_t)(const void *)((account) + 1) -
(size_t)(const void *)(account) == 1) && (__s2_len =
__builtin_strlen (account), __s2_len < 4) ? (__builtin_constant_p
("sip:") && ((size_t)(const void *)(("sip:") + 1) - (
size_t)(const void *)("sip:") == 1) ? __builtin_strcmp ("sip:"
, account) : (- (__extension__ ({ const unsigned char *__s2 =
(const unsigned char *) (const char *) ("sip:"); int __result
= (((const unsigned char *) (const char *) (account))[0] - __s2
[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (account))[1] - __s2
[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (account))[2] - __s2
[2]); if (__s2_len > 2 && __result == 0) __result =
(((const unsigned char *) (const char *) (account))[3] - __s2
[3]); } } __result; })))) : __builtin_strcmp ("sip:", account
)))); }) : strncmp ("sip:", account, 4)))
) {
2456 return;
2457 }
2458
2459 if (!(yn = switch_event_get_header(event, "mwi-messages-waiting")switch_event_get_header_idx(event, "mwi-messages-waiting", -1
)
)) {
2460 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2460, ((void*)0)
, SWITCH_LOG_ERROR, "Missing required Header 'MWI-Messages-Waiting'\n");
2461 return;
2462 }
2463 dup_account = strdup(account)(__extension__ (__builtin_constant_p (account) && ((size_t
)(const void *)((account) + 1) - (size_t)(const void *)(account
) == 1) ? (((const char *) (account))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (account
) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, account
, __len); __retval; })) : __strdup (account)))
;
2464 switch_assert(dup_account != NULL)((dup_account != ((void*)0)) ? (void) (0) : __assert_fail ("dup_account != ((void*)0)"
, "mod_skinny.c", 2464, __PRETTY_FUNCTION__))
;
2465 switch_split_user_domain(dup_account, &user, &host);
2466
2467 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2467, ((void*)0)
, SWITCH_LOG_DEBUG, "MWI Event received for account %s with messages waiting %s\n", account, yn);
2468
2469 if ((pname = switch_event_get_header(event, "skinny-profile")switch_event_get_header_idx(event, "skinny-profile", -1))) {
2470 if (!(profile = skinny_find_profile(pname))) {
2471 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2471, ((void*)0)
, SWITCH_LOG_DEBUG, "No profile %s\n", pname);
2472 }
2473 }
2474
2475 if (!profile) {
2476 if (!host || !(profile = skinny_find_profile_by_domain(host))) {
2477 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2477, ((void*)0)
, SWITCH_LOG_ERROR, "Cannot find profile with domain %s\n", switch_str_nil(host)(host ? host : ""));
2478 switch_safe_free(dup_account)if (dup_account) {free(dup_account);dup_account=((void*)0);};
2479 return;
2480 }
2481 }
2482
2483 count_str = switch_event_get_header(event, "mwi-voice-message")switch_event_get_header_idx(event, "mwi-voice-message", -1);
2484
2485 if ((sql = switch_mprintf(
2486 "SELECT device_name, device_instance FROM skinny_lines "
2487 "WHERE value='%s' AND line_instance=1", user))) {
2488 struct skinny_message_waiting_event_handler_helper helper = {0};
2489 helper.profile = profile;
2490 helper.yn = switch_true(yn);
2491 if (count_str) {
2492 sscanf(count_str,"%d/%d (%d/%d)",
2493 &helper.total_new_messages, &helper.total_saved_messages,
2494 &helper.total_new_urgent_messages, &helper.total_saved_urgent_messages);
2495 }
2496 skinny_execute_sql_callback(profile, profile->sql_mutex, sql, skinny_message_waiting_event_handler_callback, &helper);
2497 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
2498 }
2499
2500 switch_safe_free(dup_account)if (dup_account) {free(dup_account);dup_account=((void*)0);};
2501}
2502
2503
2504static void skinny_trap_event_handler(switch_event_t *event)
2505{
2506 const char *cond = switch_event_get_header(event, "condition")switch_event_get_header_idx(event, "condition", -1);
2507
2508
2509 if (cond && !strcmp(cond, "network-address-change")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(cond) && __builtin_constant_p ("network-address-change"
) && (__s1_len = __builtin_strlen (cond), __s2_len = __builtin_strlen
("network-address-change"), (!((size_t)(const void *)((cond)
+ 1) - (size_t)(const void *)(cond) == 1) || __s1_len >= 4
) && (!((size_t)(const void *)(("network-address-change"
) + 1) - (size_t)(const void *)("network-address-change") == 1
) || __s2_len >= 4)) ? __builtin_strcmp (cond, "network-address-change"
) : (__builtin_constant_p (cond) && ((size_t)(const void
*)((cond) + 1) - (size_t)(const void *)(cond) == 1) &&
(__s1_len = __builtin_strlen (cond), __s1_len < 4) ? (__builtin_constant_p
("network-address-change") && ((size_t)(const void *
)(("network-address-change") + 1) - (size_t)(const void *)("network-address-change"
) == 1) ? __builtin_strcmp (cond, "network-address-change") :
(__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) ("network-address-change"); int __result
= (((const unsigned char *) (const char *) (cond))[0] - __s2
[0]); if (__s1_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (cond))[1] - __s2
[1]); if (__s1_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (cond))[2] - __s2
[2]); if (__s1_len > 2 && __result == 0) __result =
(((const unsigned char *) (const char *) (cond))[3] - __s2[3
]); } } __result; }))) : (__builtin_constant_p ("network-address-change"
) && ((size_t)(const void *)(("network-address-change"
) + 1) - (size_t)(const void *)("network-address-change") == 1
) && (__s2_len = __builtin_strlen ("network-address-change"
), __s2_len < 4) ? (__builtin_constant_p (cond) &&
((size_t)(const void *)((cond) + 1) - (size_t)(const void *)
(cond) == 1) ? __builtin_strcmp (cond, "network-address-change"
) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (cond); int __result = (((const unsigned
char *) (const char *) ("network-address-change"))[0] - __s2
[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) ("network-address-change"
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) ("network-address-change"
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) ("network-address-change"
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (cond
, "network-address-change")))); })
&& globals.auto_restart) {
2510 const char *old_ip4 = switch_event_get_header_nil(event, "network-address-previous-v4")(switch_event_get_header_idx(event, "network-address-previous-v4"
, -1) ? switch_event_get_header_idx(event, "network-address-previous-v4"
, -1) : "")
;
2511 const char *new_ip4 = switch_event_get_header_nil(event, "network-address-change-v4")(switch_event_get_header_idx(event, "network-address-change-v4"
, -1) ? switch_event_get_header_idx(event, "network-address-change-v4"
, -1) : "")
;
2512 const char *old_ip6 = switch_event_get_header_nil(event, "network-address-previous-v6")(switch_event_get_header_idx(event, "network-address-previous-v6"
, -1) ? switch_event_get_header_idx(event, "network-address-previous-v6"
, -1) : "")
;
2513 const char *new_ip6 = switch_event_get_header_nil(event, "network-address-change-v6")(switch_event_get_header_idx(event, "network-address-change-v6"
, -1) ? switch_event_get_header_idx(event, "network-address-change-v6"
, -1) : "")
;
2514 switch_hash_index_t *hi;
2515 const void *var;
2516 void *val;
2517 skinny_profile_t *profile;
2518
2519 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2519, ((void*)0)
, SWITCH_LOG_INFO, "EVENT_TRAP: IP change detected\n");
2520 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2520, ((void*)0)
, SWITCH_LOG_INFO, "IP change detected [%s]->[%s] [%s]->[%s]\n", old_ip4, new_ip4, old_ip6, new_ip6);
2521
2522 switch_mutex_lock(globals.mutex);
2523 if (globals.profile_hash) {
2524 for (hi = switch_core_hash_first(globals.profile_hash)switch_core_hash_first_iter(globals.profile_hash, ((void*)0)); hi; hi = switch_core_hash_next(&hi)) {
2525 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
2526 if ((profile = (skinny_profile_t *) val) && profile->auto_restart) {
2527 if (!strcmp(profile->ip, old_ip4)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(profile->ip) && __builtin_constant_p (old_ip4) &&
(__s1_len = __builtin_strlen (profile->ip), __s2_len = __builtin_strlen
(old_ip4), (!((size_t)(const void *)((profile->ip) + 1) -
(size_t)(const void *)(profile->ip) == 1) || __s1_len >=
4) && (!((size_t)(const void *)((old_ip4) + 1) - (size_t
)(const void *)(old_ip4) == 1) || __s2_len >= 4)) ? __builtin_strcmp
(profile->ip, old_ip4) : (__builtin_constant_p (profile->
ip) && ((size_t)(const void *)((profile->ip) + 1) -
(size_t)(const void *)(profile->ip) == 1) && (__s1_len
= __builtin_strlen (profile->ip), __s1_len < 4) ? (__builtin_constant_p
(old_ip4) && ((size_t)(const void *)((old_ip4) + 1) -
(size_t)(const void *)(old_ip4) == 1) ? __builtin_strcmp (profile
->ip, old_ip4) : (__extension__ ({ const unsigned char *__s2
= (const unsigned char *) (const char *) (old_ip4); int __result
= (((const unsigned char *) (const char *) (profile->ip))
[0] - __s2[0]); if (__s1_len > 0 && __result == 0)
{ __result = (((const unsigned char *) (const char *) (profile
->ip))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
profile->ip))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (profile->ip))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(old_ip4) && ((size_t)(const void *)((old_ip4) + 1) -
(size_t)(const void *)(old_ip4) == 1) && (__s2_len =
__builtin_strlen (old_ip4), __s2_len < 4) ? (__builtin_constant_p
(profile->ip) && ((size_t)(const void *)((profile
->ip) + 1) - (size_t)(const void *)(profile->ip) == 1) ?
__builtin_strcmp (profile->ip, old_ip4) : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (profile->ip); int __result = (((const unsigned char
*) (const char *) (old_ip4))[0] - __s2[0]); if (__s2_len >
0 && __result == 0) { __result = (((const unsigned char
*) (const char *) (old_ip4))[1] - __s2[1]); if (__s2_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (old_ip4))[2] - __s2[2]); if (__s2_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) (old_ip4))[3] - __s2[3]); } } __result; })
))) : __builtin_strcmp (profile->ip, old_ip4)))); })
) {
2528 skinny_profile_set(profile, "ip", new_ip4);
2529 } else if (!strcmp(profile->ip, old_ip6)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(profile->ip) && __builtin_constant_p (old_ip6) &&
(__s1_len = __builtin_strlen (profile->ip), __s2_len = __builtin_strlen
(old_ip6), (!((size_t)(const void *)((profile->ip) + 1) -
(size_t)(const void *)(profile->ip) == 1) || __s1_len >=
4) && (!((size_t)(const void *)((old_ip6) + 1) - (size_t
)(const void *)(old_ip6) == 1) || __s2_len >= 4)) ? __builtin_strcmp
(profile->ip, old_ip6) : (__builtin_constant_p (profile->
ip) && ((size_t)(const void *)((profile->ip) + 1) -
(size_t)(const void *)(profile->ip) == 1) && (__s1_len
= __builtin_strlen (profile->ip), __s1_len < 4) ? (__builtin_constant_p
(old_ip6) && ((size_t)(const void *)((old_ip6) + 1) -
(size_t)(const void *)(old_ip6) == 1) ? __builtin_strcmp (profile
->ip, old_ip6) : (__extension__ ({ const unsigned char *__s2
= (const unsigned char *) (const char *) (old_ip6); int __result
= (((const unsigned char *) (const char *) (profile->ip))
[0] - __s2[0]); if (__s1_len > 0 && __result == 0)
{ __result = (((const unsigned char *) (const char *) (profile
->ip))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
profile->ip))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (profile->ip))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(old_ip6) && ((size_t)(const void *)((old_ip6) + 1) -
(size_t)(const void *)(old_ip6) == 1) && (__s2_len =
__builtin_strlen (old_ip6), __s2_len < 4) ? (__builtin_constant_p
(profile->ip) && ((size_t)(const void *)((profile
->ip) + 1) - (size_t)(const void *)(profile->ip) == 1) ?
__builtin_strcmp (profile->ip, old_ip6) : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (profile->ip); int __result = (((const unsigned char
*) (const char *) (old_ip6))[0] - __s2[0]); if (__s2_len >
0 && __result == 0) { __result = (((const unsigned char
*) (const char *) (old_ip6))[1] - __s2[1]); if (__s2_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (old_ip6))[2] - __s2[2]); if (__s2_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) (old_ip6))[3] - __s2[3]); } } __result; })
))) : __builtin_strcmp (profile->ip, old_ip6)))); })
) {
2530 skinny_profile_set(profile, "ip", new_ip6);
2531 }
2532 skinny_profile_respawn(profile, 0);
2533 }
2534 }
2535 }
2536 switch_mutex_unlock(globals.mutex);
2537 }
2538
2539}
2540
2541/*****************************************************************************/
2542SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load)switch_status_t mod_skinny_load (switch_loadable_module_interface_t
**module_interface, switch_memory_pool_t *pool)
2543{
2544 switch_hash_index_t *hi;
2545 /* globals init */
2546 memset(&globals, 0, sizeof(globals));
2547
2548 if (switch_core_new_memory_pool(&globals.pool)switch_core_perform_new_memory_pool(&globals.pool, "mod_skinny.c"
, (const char *)__func__, 2548)
!= SWITCH_STATUS_SUCCESS) {
2549 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2549, ((void*)0)
, SWITCH_LOG_ERROR, "OH OH no pool\n");
2550 return SWITCH_STATUS_TERM;
2551 }
2552 switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED0x1, globals.pool);
2553 switch_core_hash_init(&globals.profile_hash)switch_core_hash_init_case(&globals.profile_hash, SWITCH_TRUE
)
;
2554 globals.running = 1;
2555 globals.auto_restart = SWITCH_TRUE;
2556
2557 load_skinny_config();
2558
2559 /* at least one profile */
2560 if (switch_core_hash_empty( globals.profile_hash)) {
2561 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2561, ((void*)0)
, SWITCH_LOG_ERROR, "No profile found!\n");
2562 return SWITCH_STATUS_TERM;
2563 }
2564 /* bind to events */
2565 if ((switch_event_bind_removable(modname, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_CALL_STATE"skinny::call_state", skinny_call_state_event_handler, NULL((void*)0), &globals.call_state_node) != SWITCH_STATUS_SUCCESS)) {
2566 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2566, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't bind our call_state handler!\n");
2567 return SWITCH_STATUS_TERM;
2568 }
2569 if ((switch_event_bind_removable(modname, SWITCH_EVENT_MESSAGE_WAITING, NULL((void*)0), skinny_message_waiting_event_handler, NULL((void*)0), &globals.message_waiting_node) != SWITCH_STATUS_SUCCESS)) {
2570 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2570, ((void*)0)
, SWITCH_LOG_WARNING, "Couldn't bind our message waiting handler!\n");
2571 /* Not such severe to prevent loading */
2572 }
2573 if ((switch_event_bind_removable(modname, SWITCH_EVENT_TRAP, NULL((void*)0), skinny_trap_event_handler, NULL((void*)0), &globals.trap_node) != SWITCH_STATUS_SUCCESS)) {
2574 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2574, ((void*)0)
, SWITCH_LOG_WARNING, "Couldn't bind our trap handler!\n");
2575 /* Not such severe to prevent loading */
2576 }
2577 if ((switch_event_bind_removable(modname, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_USER_TO_DEVICE"skinny::user_to_device", skinny_user_to_device_event_handler, NULL((void*)0), &globals.user_to_device_node) != SWITCH_STATUS_SUCCESS)) {
2578 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2578, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't bind our user_to_device handler!\n");
2579 /* Not such severe to prevent loading */
2580 }
2581
2582 /* reserve events */
2583 if (switch_event_reserve_subclass(SKINNY_EVENT_REGISTER)switch_event_reserve_subclass_detailed("mod_skinny.c", "skinny::register"
)
!= SWITCH_STATUS_SUCCESS) {
2584 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2584, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", SKINNY_EVENT_REGISTER"skinny::register");
2585 return SWITCH_STATUS_TERM;
2586 }
2587 if (switch_event_reserve_subclass(SKINNY_EVENT_UNREGISTER)switch_event_reserve_subclass_detailed("mod_skinny.c", "skinny::unregister"
)
!= SWITCH_STATUS_SUCCESS) {
2588 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2588, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", SKINNY_EVENT_UNREGISTER"skinny::unregister");
2589 return SWITCH_STATUS_TERM;
2590 }
2591 if (switch_event_reserve_subclass(SKINNY_EVENT_EXPIRE)switch_event_reserve_subclass_detailed("mod_skinny.c", "skinny::expire"
)
!= SWITCH_STATUS_SUCCESS) {
2592 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2592, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", SKINNY_EVENT_EXPIRE"skinny::expire");
2593 return SWITCH_STATUS_TERM;
2594 }
2595 if (switch_event_reserve_subclass(SKINNY_EVENT_ALARM)switch_event_reserve_subclass_detailed("mod_skinny.c", "skinny::alarm"
)
!= SWITCH_STATUS_SUCCESS) {
2596 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2596, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", SKINNY_EVENT_ALARM"skinny::alarm");
2597 return SWITCH_STATUS_TERM;
2598 }
2599 if (switch_event_reserve_subclass(SKINNY_EVENT_CALL_STATE)switch_event_reserve_subclass_detailed("mod_skinny.c", "skinny::call_state"
)
!= SWITCH_STATUS_SUCCESS) {
2600 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2600, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", SKINNY_EVENT_CALL_STATE"skinny::call_state");
2601 return SWITCH_STATUS_TERM;
2602 }
2603 if (switch_event_reserve_subclass(SKINNY_EVENT_USER_TO_DEVICE)switch_event_reserve_subclass_detailed("mod_skinny.c", "skinny::user_to_device"
)
!= SWITCH_STATUS_SUCCESS) {
2604 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2604, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", SKINNY_EVENT_USER_TO_DEVICE"skinny::user_to_device");
2605 return SWITCH_STATUS_TERM;
2606 }
2607 if (switch_event_reserve_subclass(SKINNY_EVENT_DEVICE_TO_USER)switch_event_reserve_subclass_detailed("mod_skinny.c", "skinny::device_to_user"
)
!= SWITCH_STATUS_SUCCESS) {
2608 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_skinny.c", (const char *)__func__
, 2608, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", SKINNY_EVENT_DEVICE_TO_USER"skinny::device_to_user");
2609 return SWITCH_STATUS_TERM;
2610 }
2611
2612 /* connect my internal structure to the blank pointer passed to me */
2613 *module_interface = switch_loadable_module_create_module_interface(globals.pool, modname);
2614 skinny_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
2615 skinny_endpoint_interface->interface_name = "skinny";
2616 skinny_endpoint_interface->io_routines = &skinny_io_routines;
2617 skinny_endpoint_interface->state_handler = &skinny_state_handlers;
2618
2619 skinny_api_register(module_interface);
2620
2621 /* launch listeners */
2622 switch_mutex_lock(globals.mutex);
2623 for (hi = switch_core_hash_first(globals.profile_hash)switch_core_hash_first_iter(globals.profile_hash, ((void*)0)); hi; hi = switch_core_hash_next(&hi)) {
2624 void *val;
2625 skinny_profile_t *profile;
2626
2627 switch_core_hash_this(hi, NULL((void*)0), NULL((void*)0), &val);
2628 profile = (skinny_profile_t *) val;
2629
2630 launch_skinny_profile_thread(profile);
2631 }
2632 switch_mutex_unlock(globals.mutex);
2633
2634 /* indicate that the module should continue to be loaded */
2635 return SWITCH_STATUS_SUCCESS;
2636}
2637
2638SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skinny_shutdown)switch_status_t mod_skinny_shutdown (void)
2639{
2640 switch_hash_index_t *hi;
2641 void *val;
2642 switch_memory_pool_t *pool = globals.pool;
2643 switch_mutex_t *mutex = globals.mutex;
2644 int sanity = 0;
2645
2646 skinny_api_unregister();
2647
2648 /* release events */
2649 switch_event_unbind(&globals.user_to_device_node);
2650 switch_event_unbind(&globals.call_state_node);
2651 switch_event_unbind(&globals.message_waiting_node);
2652 switch_event_unbind(&globals.trap_node);
2653 switch_event_free_subclass(SKINNY_EVENT_REGISTER)switch_event_free_subclass_detailed("mod_skinny.c", "skinny::register"
)
;
2654 switch_event_free_subclass(SKINNY_EVENT_UNREGISTER)switch_event_free_subclass_detailed("mod_skinny.c", "skinny::unregister"
)
;
2655 switch_event_free_subclass(SKINNY_EVENT_EXPIRE)switch_event_free_subclass_detailed("mod_skinny.c", "skinny::expire"
)
;
2656 switch_event_free_subclass(SKINNY_EVENT_ALARM)switch_event_free_subclass_detailed("mod_skinny.c", "skinny::alarm"
)
;
2657 switch_event_free_subclass(SKINNY_EVENT_CALL_STATE)switch_event_free_subclass_detailed("mod_skinny.c", "skinny::call_state"
)
;
2658 switch_event_free_subclass(SKINNY_EVENT_USER_TO_DEVICE)switch_event_free_subclass_detailed("mod_skinny.c", "skinny::user_to_device"
)
;
2659 switch_event_free_subclass(SKINNY_EVENT_DEVICE_TO_USER)switch_event_free_subclass_detailed("mod_skinny.c", "skinny::device_to_user"
)
;
2660
2661 switch_mutex_lock(mutex);
2662
2663 globals.running = 0;
2664
2665 /* kill listeners */
2666 walk_listeners(kill_listener, NULL((void*)0));
2667
2668 /* close sockets */
2669 switch_mutex_lock(globals.mutex);
2670 for (hi = switch_core_hash_first(globals.profile_hash)switch_core_hash_first_iter(globals.profile_hash, ((void*)0)); hi; hi = switch_core_hash_next(&hi)) {
2671 skinny_profile_t *profile;
2672 switch_core_hash_this(hi, NULL((void*)0), NULL((void*)0), &val);
2673 profile = (skinny_profile_t *) val;
2674
2675 close_socket(&profile->sock, profile);
2676
2677 while (profile->listener_threads) {
2678 switch_yield(100000)switch_sleep(100000);;
2679 walk_listeners(kill_listener, NULL((void*)0));
2680 if (++sanity >= 200) {
2681 break;
2682 }
2683 }
2684 switch_core_destroy_memory_pool(&profile->pool)switch_core_perform_destroy_memory_pool(&profile->pool
, "mod_skinny.c", (const char *)__func__, 2684)
;
2685 }
2686 switch_mutex_unlock(globals.mutex);
2687
2688 switch_core_hash_destroy(&globals.profile_hash);
2689 memset(&globals, 0, sizeof(globals));
2690 switch_mutex_unlock(mutex);
2691 switch_core_destroy_memory_pool(&pool)switch_core_perform_destroy_memory_pool(&pool, "mod_skinny.c"
, (const char *)__func__, 2691)
;
2692 return SWITCH_STATUS_SUCCESS;
2693}
2694
2695/* For Emacs:
2696 * Local Variables:
2697 * mode:c
2698 * indent-tabs-mode:t
2699 * tab-width:4
2700 * c-basic-offset:4
2701 * End:
2702 * For VIM:
2703 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
2704 */