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.h -- Skinny Call Control Protocol (SCCP) Endpoint Module 30 * 31 */ 32 33 #ifndef _MOD_SKINNY_H 34 #define _MOD_SKINNY_H 35 36 #include <switch.h> 37 38 /*****************************************************************************/ 39 /* UTILITY MACROS */ 40 /*****************************************************************************/ 41 #define empty_null(a) ((a)?(a):NULL) 42 #define empty_null2(a,b) ((a)?(a):empty_null(b)) 43 44 /*****************************************************************************/ 45 /* LOGGING FUNCTIONS */ 46 /*****************************************************************************/ 47 #define skinny_undef_str(x) (zstr(x) ? "_undef_" : x) 48 49 #define skinny_log_l(listener, level, _fmt, ...) switch_log_printf(SWITCH_CHANNEL_LOG, level, \ 50 "[%s:%d @ %s:%d] " _fmt, skinny_undef_str(listener->device_name), listener->device_instance, skinny_undef_str(listener->remote_ip), \ 51 listener->remote_port, __VA_ARGS__) 52 53 #define skinny_log_l_msg(listener, level, _fmt) switch_log_printf(SWITCH_CHANNEL_LOG, level, \ 54 "[%s:%d @ %s:%d] " _fmt, skinny_undef_str(listener->device_name), listener->device_instance, skinny_undef_str(listener->remote_ip), \ 55 listener->remote_port) 56 57 #define skinny_log_l_ffl(listener, file, func, line, level, _fmt, ...) switch_log_printf( \ 58 SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, level, \ 59 "[%s:%d @ %s:%d] " _fmt, skinny_undef_str(listener->device_name), listener->device_instance, skinny_undef_str(listener->remote_ip), \ 60 listener->remote_port, __VA_ARGS__) 61 62 #define skinny_log_l_ffl_msg(listener, file, func, line, level, _fmt) switch_log_printf( \ 63 SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, level, \ 64 "[%s:%d @ %s:%d] " _fmt, skinny_undef_str(listener->device_name), listener->device_instance, skinny_undef_str(listener->remote_ip), \ 65 listener->remote_port) 66 67 #define skinny_log_ls(listener, session, level, _fmt, ...) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), level, \ 68 "[%s:%d @ %s:%d] " _fmt, skinny_undef_str(listener->device_name), listener->device_instance, skinny_undef_str(listener->remote_ip), \ 69 listener->remote_port, __VA_ARGS__) 70 71 #define skinny_log_ls_msg(listener, session, level, _fmt) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), level, \ 72 "[%s:%d @ %s:%d] " _fmt, skinny_undef_str(listener->device_name), listener->device_instance, skinny_undef_str(listener->remote_ip), \ 73 listener->remote_port) 74 75 #define skinny_log_s(session, level, _fmt, ...) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), level, \ 76 _fmt, __VA_ARGS__) 77 78 79 /*****************************************************************************/ 80 /* MODULE TYPES */ 81 /*****************************************************************************/ 82 #define SKINNY_EVENT_REGISTER "skinny::register" 83 #define SKINNY_EVENT_UNREGISTER "skinny::unregister" 84 #define SKINNY_EVENT_EXPIRE "skinny::expire" 85 #define SKINNY_EVENT_ALARM "skinny::alarm" 86 #define SKINNY_EVENT_XML_ALARM "skinny::xml_alarm" 87 #define SKINNY_EVENT_CALL_STATE "skinny::call_state" 88 #define SKINNY_EVENT_USER_TO_DEVICE "skinny::user_to_device" 89 #define SKINNY_EVENT_DEVICE_TO_USER "skinny::device_to_user" 90 91 struct skinny_globals { 92 int running; 93 switch_memory_pool_t *pool; 94 switch_mutex_t *mutex; 95 switch_hash_t *profile_hash; 96 switch_event_node_t *user_to_device_node; 97 switch_event_node_t *call_state_node; 98 switch_event_node_t *message_waiting_node; 99 switch_event_node_t *trap_node; 100 int auto_restart; 101 }; 102 typedef struct skinny_globals skinny_globals_t; 103 104 extern skinny_globals_t skinny_globals; 105 106 typedef enum { 107 PFLAG_LISTENER_READY = (1 << 0), 108 PFLAG_SHOULD_RESPAWN = (1 << 1), 109 PFLAG_RESPAWN = (1 << 2), 110 } profile_flag_t; 111 112 struct skinny_profile { 113 /* prefs */ 114 char *name; 115 char *domain; 116 char *ip; 117 unsigned int port; 118 char *dialplan; 119 char *context; 120 char *patterns_dialplan; 121 char *patterns_context; 122 uint32_t keep_alive; 123 uint32_t digit_timeout; 124 char date_format[6]; 125 int debug; 126 int auto_restart; 127 int non_blocking; 128 switch_hash_t *soft_key_set_sets_hash; 129 switch_hash_t *device_type_params_hash; 130 /* lock on device names for multiple connection handling */ 131 switch_mutex_t *device_name_lock_mutex; 132 switch_hash_t *device_name_lock_hash; 133 /* extensions */ 134 char *ext_voicemail; 135 char *ext_redial; 136 char *ext_meetme; 137 char *ext_pickup; 138 char *ext_cfwdall; 139 /* db */ 140 char *dbname; 141 char *odbc_dsn; 142 switch_odbc_handle_t *master_odbc; 143 switch_mutex_t *sql_mutex; 144 /* stats */ 145 uint32_t ib_calls; 146 uint32_t ob_calls; 147 uint32_t ib_failed_calls; 148 uint32_t ob_failed_calls; 149 /* listener */ 150 int listener_threads; 151 switch_mutex_t *listener_mutex; 152 switch_socket_t *sock; 153 switch_mutex_t *sock_mutex; 154 struct listener *listeners; 155 int flags; 156 switch_mutex_t *flag_mutex; 157 /* call id */ 158 uint32_t next_call_id; 159 /* others */ 160 switch_memory_pool_t *pool; 161 }; 162 typedef struct skinny_profile skinny_profile_t; 163 164 struct skinny_device_type_params { 165 char firmware_version[16]; 166 }; 167 typedef struct skinny_device_type_params skinny_device_type_params_t; 168 169 typedef enum { 170 SKINNY_ACTION_PROCESS, 171 SKINNY_ACTION_DROP, 172 SKINNY_ACTION_WAIT 173 } skinny_action_t; 174 175 176 177 /*****************************************************************************/ 178 /* DEVICE NAME LOCK TYPES */ 179 /*****************************************************************************/ 180 typedef enum { 181 DNLFLAG_INUSE = (1 << 0), 182 } device_name_lock_flag_t; 183 184 struct device_name_lock { 185 char device_name[16]; 186 switch_mutex_t *flag_mutex; 187 uint32_t flags; 188 }; 189 190 typedef struct device_name_lock device_name_lock_t; 191 192 /*****************************************************************************/ 193 /* LISTENERS TYPES */ 194 /*****************************************************************************/ 195 196 typedef enum { 197 LFLAG_RUNNING = (1 << 0), 198 } listener_flag_t; 199 200 #define SKINNY_MAX_LINES 42 201 struct listener { 202 skinny_profile_t *profile; 203 char device_name[16]; 204 uint32_t device_instance; 205 uint32_t device_type; 206 207 char firmware_version[16]; 208 char *soft_key_set_set; 209 210 switch_socket_t *sock; 211 switch_memory_pool_t *pool; 212 switch_thread_rwlock_t *rwlock; 213 char remote_ip[50]; 214 switch_port_t remote_port; 215 char local_ip[50]; 216 switch_port_t local_port; 217 switch_mutex_t *flag_mutex; 218 uint32_t flags; 219 time_t expire_time; 220 time_t connect_time; 221 switch_time_t digit_timeout_time; 222 struct listener *next; 223 char *ext_voicemail; 224 char *ext_redial; 225 char *ext_meetme; 226 char *ext_pickup; 227 char *ext_cfwdall; 228 char *ext_autodial; 229 }; 230 231 typedef struct listener listener_t; 232 233 typedef switch_status_t (*skinny_listener_callback_func_t) (listener_t *listener, void *pvt); 234 235 /*****************************************************************************/ 236 /* CHANNEL TYPES */ 237 /*****************************************************************************/ 238 typedef enum { 239 TFLAG_FORCE_ROUTE = (1 << 0), 240 TFLAG_EARLY_MEDIA = (1 << 1), 241 TFLAG_IO = (1 << 2), 242 TFLAG_READING = (1 << 3), 243 TFLAG_WRITING = (1 << 4) 244 } TFLAGS; 245 246 typedef enum { 247 GFLAG_MY_CODEC_PREFS = (1 << 0) 248 } GFLAGS; 249 250 struct private_object { 251 unsigned int flags; 252 switch_mutex_t *flag_mutex; 253 switch_frame_t read_frame; 254 unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; 255 switch_core_session_t *session; 256 switch_caller_profile_t *caller_profile; 257 switch_mutex_t *mutex; 258 259 /* identification */ 260 skinny_profile_t *profile; 261 uint32_t call_id; 262 uint32_t party_id; 263 264 /* related calls */ 265 uint32_t transfer_to_call_id; 266 uint32_t transfer_from_call_id; 267 268 /* codec */ 269 char *iananame; 270 switch_codec_t read_codec; 271 switch_codec_t write_codec; 272 switch_codec_implementation_t read_impl; 273 switch_codec_implementation_t write_impl; 274 unsigned long rm_rate; 275 uint32_t codec_ms; 276 char *rm_encoding; 277 char *rm_fmtp; 278 switch_payload_t agreed_pt; 279 /* RTP */ 280 switch_rtp_t *rtp_session; 281 char *local_sdp_audio_ip; 282 switch_port_t local_sdp_audio_port; 283 char *remote_sdp_audio_ip; 284 switch_port_t remote_sdp_audio_port; 285 }; 286 287 typedef struct private_object private_t; 288 289 /*****************************************************************************/ 290 /* PROFILES FUNCTIONS */ 291 /*****************************************************************************/ 292 skinny_profile_t *skinny_find_profile(const char *profile_name); 293 switch_status_t skinny_profile_dump(const skinny_profile_t *profile, switch_stream_handle_t *stream); 294 switch_status_t skinny_profile_find_listener_by_device_name(skinny_profile_t *profile, const char *device_name, listener_t **listener); 295 switch_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); 296 char * skinny_profile_find_session_uuid(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id); 297 #ifdef SWITCH_DEBUG_RWLOCKS 298 switch_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); 299 #define skinny_profile_find_session(profile, listener, line_instance_p, call_id) skinny_profile_perform_find_session(profile, listener, line_instance_p, call_id, __FILE__, __SWITCH_FUNC__, __LINE__) 300 #else 301 switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id); 302 #endif 303 switch_status_t dump_device(skinny_profile_t *profile, const char *device_name, switch_stream_handle_t *stream); 304 switch_status_t skinny_profile_respawn(skinny_profile_t *profile, int force); 305 switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, const char *val); 306 void profile_walk_listeners(skinny_profile_t *profile, skinny_listener_callback_func_t callback, void *pvt); 307 308 /*****************************************************************************/ 309 /* SQL FUNCTIONS */ 310 /*****************************************************************************/ 311 switch_cache_db_handle_t *skinny_get_db_handle(skinny_profile_t *profile); 312 switch_status_t skinny_execute_sql(skinny_profile_t *profile, char *sql, switch_mutex_t *mutex); 313 switch_bool_t skinny_execute_sql_callback(skinny_profile_t *profile, 314 switch_mutex_t *mutex, char *sql, switch_core_db_callback_func_t callback, void *pdata); 315 316 /*****************************************************************************/ 317 /* LISTENER FUNCTIONS */ 318 /*****************************************************************************/ 319 uint8_t listener_is_ready(listener_t *listener); 320 switch_status_t kill_listener(listener_t *listener, void *pvt); 321 switch_status_t keepalive_listener(listener_t *listener, void *pvt); 322 void skinny_clean_listener_from_db(listener_t *listener); 323 void skinny_clean_device_from_db(listener_t *listener, char *device_name); 324 325 /*****************************************************************************/ 326 /* DEVICE NAME LOCK FUNCTIONS */ 327 /*****************************************************************************/ 328 void skinny_lock_device_name(listener_t *listener, char *device_name); 329 void skinny_unlock_device_name(listener_t *listener, char *device_name); 330 331 /*****************************************************************************/ 332 /* CHANNEL FUNCTIONS */ 333 /*****************************************************************************/ 334 void 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); 335 #define skinny_line_set_state(listener, line_instance, call_id, call_state) skinny_line_perform_set_state(__FILE__, __SWITCH_FUNC__, __LINE__, listener, line_instance, call_id, call_state) 336 337 uint32_t skinny_line_get_state(listener_t *listener, uint32_t line_instance, uint32_t call_id); 338 uint32_t skinny_line_count_active(listener_t *listener); 339 340 switch_status_t skinny_tech_set_codec(private_t *tech_pvt, int force); 341 void tech_init(private_t *tech_pvt, skinny_profile_t *profile, switch_core_session_t *session); 342 switch_status_t channel_on_init(switch_core_session_t *session); 343 switch_status_t channel_on_hangup(switch_core_session_t *session); 344 switch_status_t channel_on_destroy(switch_core_session_t *session); 345 switch_status_t channel_on_routing(switch_core_session_t *session); 346 switch_status_t channel_on_exchange_media(switch_core_session_t *session); 347 switch_status_t channel_on_soft_execute(switch_core_session_t *session); 348 switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, 349 switch_caller_profile_t *outbound_profile, 350 switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause); 351 switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id); 352 switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id); 353 switch_status_t channel_kill_channel(switch_core_session_t *session, int sig); 354 355 /*****************************************************************************/ 356 /* MODULE FUNCTIONS */ 357 /*****************************************************************************/ 358 switch_endpoint_interface_t *skinny_get_endpoint_interface(); 359 360 /*****************************************************************************/ 361 /* TEXT FUNCTIONS */ 362 /*****************************************************************************/ 363 #define skinny_textid2raw(label) (label > 0 ? switch_mprintf("\200%c", label) : switch_mprintf("")) 364 char *skinny_format_message(const char *str); 365 366 #define SKINNY_MAX_STRING 16384 367 368 #endif /* _MOD_SKINNY_H */ 369 370 /* For Emacs: 371 * Local Variables: 372 * mode:c 373 * indent-tabs-mode:t 374 * tab-width:4 375 * c-basic-offset:4 376 * End: 377 * For VIM: 378 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: 379 */ 380 381