/* * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application * Copyright (C) 2010, Mathieu Parent * * Version: MPL 1.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application * * The Initial Developer of the Original Code is * Mathieu Parent * Portions created by the Initial Developer are Copyright (C) * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Mathieu Parent * * * mod_skinny.h -- Skinny Call Control Protocol (SCCP) Endpoint Module * */ #ifndef _MOD_SKINNY_H #define _MOD_SKINNY_H #include /*****************************************************************************/ /* UTILITY MACROS */ /*****************************************************************************/ #define empty_null(a) ((a)?(a):NULL) #define empty_null2(a,b) ((a)?(a):empty_null(b)) /*****************************************************************************/ /* LOGGING FUNCTIONS */ /*****************************************************************************/ #define skinny_undef_str(x) (zstr(x) ? "_undef_" : x) #define skinny_log_l(listener, level, _fmt, ...) switch_log_printf(SWITCH_CHANNEL_LOG, level, \ "[%s:%d @ %s:%d] " _fmt, skinny_undef_str(listener->device_name), listener->device_instance, skinny_undef_str(listener->remote_ip), \ listener->remote_port, __VA_ARGS__) #define skinny_log_l_msg(listener, level, _fmt) switch_log_printf(SWITCH_CHANNEL_LOG, level, \ "[%s:%d @ %s:%d] " _fmt, skinny_undef_str(listener->device_name), listener->device_instance, skinny_undef_str(listener->remote_ip), \ listener->remote_port) #define skinny_log_l_ffl(listener, file, func, line, level, _fmt, ...) switch_log_printf( \ SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, level, \ "[%s:%d @ %s:%d] " _fmt, skinny_undef_str(listener->device_name), listener->device_instance, skinny_undef_str(listener->remote_ip), \ listener->remote_port, __VA_ARGS__) #define skinny_log_l_ffl_msg(listener, file, func, line, level, _fmt) switch_log_printf( \ SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, level, \ "[%s:%d @ %s:%d] " _fmt, skinny_undef_str(listener->device_name), listener->device_instance, skinny_undef_str(listener->remote_ip), \ listener->remote_port) #define skinny_log_ls(listener, session, level, _fmt, ...) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), level, \ "[%s:%d @ %s:%d] " _fmt, skinny_undef_str(listener->device_name), listener->device_instance, skinny_undef_str(listener->remote_ip), \ listener->remote_port, __VA_ARGS__) #define skinny_log_ls_msg(listener, session, level, _fmt) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), level, \ "[%s:%d @ %s:%d] " _fmt, skinny_undef_str(listener->device_name), listener->device_instance, skinny_undef_str(listener->remote_ip), \ listener->remote_port) #define skinny_log_s(session, level, _fmt, ...) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), level, \ _fmt, __VA_ARGS__) /*****************************************************************************/ /* MODULE TYPES */ /*****************************************************************************/ #define SKINNY_EVENT_REGISTER "skinny::register" #define SKINNY_EVENT_UNREGISTER "skinny::unregister" #define SKINNY_EVENT_EXPIRE "skinny::expire" #define SKINNY_EVENT_ALARM "skinny::alarm" #define SKINNY_EVENT_XML_ALARM "skinny::xml_alarm" #define SKINNY_EVENT_CALL_STATE "skinny::call_state" #define SKINNY_EVENT_USER_TO_DEVICE "skinny::user_to_device" #define SKINNY_EVENT_DEVICE_TO_USER "skinny::device_to_user" struct skinny_globals { int running; switch_memory_pool_t *pool; switch_mutex_t *mutex; switch_hash_t *profile_hash; switch_event_node_t *user_to_device_node; switch_event_node_t *call_state_node; switch_event_node_t *message_waiting_node; switch_event_node_t *trap_node; int auto_restart; }; typedef struct skinny_globals skinny_globals_t; extern skinny_globals_t globals; typedef enum { PFLAG_LISTENER_READY = (1 << 0), PFLAG_SHOULD_RESPAWN = (1 << 1), PFLAG_RESPAWN = (1 << 2), } profile_flag_t; struct skinny_profile { /* prefs */ char *name; char *domain; char *ip; unsigned int port; char *dialplan; char *context; char *patterns_dialplan; char *patterns_context; uint32_t keep_alive; uint32_t digit_timeout; char date_format[6]; int debug; int auto_restart; int non_blocking; switch_hash_t *soft_key_set_sets_hash; switch_hash_t *device_type_params_hash; /* extensions */ char *ext_voicemail; char *ext_redial; char *ext_meetme; char *ext_pickup; char *ext_cfwdall; /* db */ char *dbname; char *odbc_dsn; switch_odbc_handle_t *master_odbc; switch_mutex_t *sql_mutex; /* stats */ uint32_t ib_calls; uint32_t ob_calls; uint32_t ib_failed_calls; uint32_t ob_failed_calls; /* listener */ int listener_threads; switch_mutex_t *listener_mutex; switch_socket_t *sock; switch_mutex_t *sock_mutex; struct listener *listeners; int flags; switch_mutex_t *flag_mutex; /* call id */ uint32_t next_call_id; /* others */ switch_memory_pool_t *pool; }; typedef struct skinny_profile skinny_profile_t; struct skinny_device_type_params { char firmware_version[16]; }; typedef struct skinny_device_type_params skinny_device_type_params_t; typedef enum { SKINNY_ACTION_PROCESS, SKINNY_ACTION_DROP, SKINNY_ACTION_WAIT } skinny_action_t; /*****************************************************************************/ /* LISTENERS TYPES */ /*****************************************************************************/ typedef enum { LFLAG_RUNNING = (1 << 0), } listener_flag_t; #define SKINNY_MAX_LINES 42 struct listener { skinny_profile_t *profile; char device_name[16]; uint32_t device_instance; uint32_t device_type; char firmware_version[16]; char *soft_key_set_set; switch_socket_t *sock; switch_memory_pool_t *pool; switch_thread_rwlock_t *rwlock; char remote_ip[50]; switch_port_t remote_port; char local_ip[50]; switch_port_t local_port; switch_mutex_t *flag_mutex; uint32_t flags; time_t expire_time; switch_time_t digit_timeout_time; struct listener *next; char *ext_voicemail; char *ext_redial; char *ext_meetme; char *ext_pickup; char *ext_cfwdall; char *ext_autodial; }; typedef struct listener listener_t; typedef switch_status_t (*skinny_listener_callback_func_t) (listener_t *listener, void *pvt); /*****************************************************************************/ /* CHANNEL TYPES */ /*****************************************************************************/ typedef enum { TFLAG_FORCE_ROUTE = (1 << 0), TFLAG_EARLY_MEDIA = (1 << 1), TFLAG_IO = (1 << 2), TFLAG_READING = (1 << 3), TFLAG_WRITING = (1 << 4) } TFLAGS; typedef enum { GFLAG_MY_CODEC_PREFS = (1 << 0) } GFLAGS; struct private_object { unsigned int flags; switch_mutex_t *flag_mutex; switch_frame_t read_frame; unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; switch_core_session_t *session; switch_caller_profile_t *caller_profile; switch_mutex_t *mutex; /* identification */ skinny_profile_t *profile; uint32_t call_id; uint32_t party_id; /* related calls */ uint32_t transfer_to_call_id; uint32_t transfer_from_call_id; /* codec */ char *iananame; switch_codec_t read_codec; switch_codec_t write_codec; switch_codec_implementation_t read_impl; switch_codec_implementation_t write_impl; unsigned long rm_rate; uint32_t codec_ms; char *rm_encoding; char *rm_fmtp; switch_payload_t agreed_pt; /* RTP */ switch_rtp_t *rtp_session; char *local_sdp_audio_ip; switch_port_t local_sdp_audio_port; char *remote_sdp_audio_ip; switch_port_t remote_sdp_audio_port; }; typedef struct private_object private_t; /*****************************************************************************/ /* PROFILES FUNCTIONS */ /*****************************************************************************/ skinny_profile_t *skinny_find_profile(const char *profile_name); switch_status_t skinny_profile_dump(const skinny_profile_t *profile, switch_stream_handle_t *stream); switch_status_t skinny_profile_find_listener_by_device_name(skinny_profile_t *profile, const char *device_name, listener_t **listener); 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); char * skinny_profile_find_session_uuid(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id); #ifdef SWITCH_DEBUG_RWLOCKS 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); #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__) #else switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id); #endif switch_status_t dump_device(skinny_profile_t *profile, const char *device_name, switch_stream_handle_t *stream); switch_status_t skinny_profile_respawn(skinny_profile_t *profile, int force); switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, const char *val); void profile_walk_listeners(skinny_profile_t *profile, skinny_listener_callback_func_t callback, void *pvt); /*****************************************************************************/ /* SQL FUNCTIONS */ /*****************************************************************************/ switch_cache_db_handle_t *skinny_get_db_handle(skinny_profile_t *profile); switch_status_t skinny_execute_sql(skinny_profile_t *profile, char *sql, switch_mutex_t *mutex); switch_bool_t skinny_execute_sql_callback(skinny_profile_t *profile, switch_mutex_t *mutex, char *sql, switch_core_db_callback_func_t callback, void *pdata); /*****************************************************************************/ /* LISTENER FUNCTIONS */ /*****************************************************************************/ uint8_t listener_is_ready(listener_t *listener); switch_status_t kill_listener(listener_t *listener, void *pvt); switch_status_t keepalive_listener(listener_t *listener, void *pvt); void skinny_clean_listener_from_db(listener_t *listener); void skinny_clean_device_from_db(listener_t *listener, char *device_name); /*****************************************************************************/ /* CHANNEL FUNCTIONS */ /*****************************************************************************/ 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); #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) uint32_t skinny_line_get_state(listener_t *listener, uint32_t line_instance, uint32_t call_id); uint32_t skinny_line_count_active(listener_t *listener); switch_status_t skinny_tech_set_codec(private_t *tech_pvt, int force); void tech_init(private_t *tech_pvt, skinny_profile_t *profile, switch_core_session_t *session); switch_status_t channel_on_init(switch_core_session_t *session); switch_status_t channel_on_hangup(switch_core_session_t *session); switch_status_t channel_on_destroy(switch_core_session_t *session); switch_status_t channel_on_routing(switch_core_session_t *session); switch_status_t channel_on_exchange_media(switch_core_session_t *session); switch_status_t channel_on_soft_execute(switch_core_session_t *session); switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, switch_caller_profile_t *outbound_profile, switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause); switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id); switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id); switch_status_t channel_kill_channel(switch_core_session_t *session, int sig); /*****************************************************************************/ /* MODULE FUNCTIONS */ /*****************************************************************************/ switch_endpoint_interface_t *skinny_get_endpoint_interface(); /*****************************************************************************/ /* TEXT FUNCTIONS */ /*****************************************************************************/ #define skinny_textid2raw(label) (label > 0 ? switch_mprintf("\200%c", label) : switch_mprintf("")) char *skinny_format_message(const char *str); #endif /* _MOD_SKINNY_H */ /* For Emacs: * Local Variables: * mode:c * indent-tabs-mode:t * tab-width:4 * c-basic-offset:4 * End: * For VIM: * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: */