some refactoring and plumbing for 1.4

This commit is contained in:
Anthony Minessale 2013-10-16 02:24:32 +05:00
parent c7ccf84a14
commit 4a172402d2
37 changed files with 1729 additions and 287 deletions

View File

@ -144,7 +144,7 @@ struct switch_core_session {
int stream_count;
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
void *private_info;
void *private_info[SWITCH_CORE_SESSION_MAX_PRIVATES];
switch_queue_t *event_queue;
switch_queue_t *message_queue;
switch_queue_t *signal_data_queue;

View File

@ -633,6 +633,8 @@ SWITCH_DECLARE(int) switch_channel_test_app_flag_key(const char *app, switch_cha
SWITCH_DECLARE(void) switch_channel_set_bridge_time(switch_channel_t *channel);
SWITCH_DECLARE(void) switch_channel_set_hangup_time(switch_channel_t *channel);
SWITCH_DECLARE(switch_call_direction_t) switch_channel_direction(switch_channel_t *channel);
SWITCH_DECLARE(void) switch_channel_set_direction(switch_channel_t *channel, switch_call_direction_t direction);
SWITCH_DECLARE(switch_core_session_t *) switch_channel_get_session(switch_channel_t *channel);
SWITCH_DECLARE(char *) switch_channel_get_flag_string(switch_channel_t *channel);
SWITCH_DECLARE(char *) switch_channel_get_cap_string(switch_channel_t *channel);

View File

@ -1070,7 +1070,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_receive_event(_In_ switch_co
\param session the session to retrieve from
\return a pointer to the private data
*/
SWITCH_DECLARE(void *) switch_core_session_get_private(_In_ switch_core_session_t *session);
SWITCH_DECLARE(void *) switch_core_session_get_private_class(_In_ switch_core_session_t *session, _In_ switch_pvt_class_t index);
#define switch_core_session_get_private(_s) switch_core_session_get_private_class(_s, SWITCH_PVT_PRIMARY)
/*!
\brief Add private user data to a session
@ -1078,7 +1079,8 @@ SWITCH_DECLARE(void *) switch_core_session_get_private(_In_ switch_core_session_
\param private_info the used data to add
\return SWITCH_STATUS_SUCCESS if data is added
*/
SWITCH_DECLARE(switch_status_t) switch_core_session_set_private(_In_ switch_core_session_t *session, _In_ void *private_info);
SWITCH_DECLARE(switch_status_t) switch_core_session_set_private_class(_In_ switch_core_session_t *session, _In_ void *private_info, _In_ switch_pvt_class_t index);
#define switch_core_session_set_private(_s, _p) switch_core_session_set_private_class(_s, _p, SWITCH_PVT_PRIMARY)
/*!
\brief Add a logical stream to a session
@ -2575,6 +2577,7 @@ SWITCH_DECLARE(int) switch_system(const char *cmd, switch_bool_t wait);
SWITCH_DECLARE(int) switch_stream_system_fork(const char *cmd, switch_stream_handle_t *stream);
SWITCH_DECLARE(int) switch_stream_system(const char *cmd, switch_stream_handle_t *stream);
SWITCH_DECLARE(switch_call_direction_t) switch_ice_direction(switch_core_session_t *session);
SWITCH_END_EXTERN_C
#endif

View File

@ -207,6 +207,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_write_frame(switch_core_sessio
SWITCH_DECLARE(int) switch_core_media_check_nat(switch_media_handle_t *smh, const char *network_ip);
SWITCH_DECLARE(switch_status_t) switch_core_media_choose_port(switch_core_session_t *session, switch_media_type_t type, int force);
SWITCH_DECLARE(switch_status_t) switch_core_media_choose_ports(switch_core_session_t *session, switch_bool_t audio, switch_bool_t video);
SWITCH_DECLARE(void) switch_core_media_check_dtmf_type(switch_core_session_t *session);
SWITCH_DECLARE(void) switch_core_media_absorb_sdp(switch_core_session_t *session);
SWITCH_DECLARE(switch_status_t) switch_core_media_proxy_remote_addr(switch_core_session_t *session, const char *sdp_str);
@ -219,6 +220,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
SWITCH_DECLARE(void)switch_core_media_set_local_sdp(switch_core_session_t *session, const char *sdp_str, switch_bool_t dup);
SWITCH_DECLARE(void) switch_core_media_patch_sdp(switch_core_session_t *session);
SWITCH_DECLARE(void) switch_core_media_set_udptl_image_sdp(switch_core_session_t *session, switch_t38_options_t *t38_options, int insist);
SWITCH_DECLARE(switch_core_media_params_t *) switch_core_media_get_mparams(switch_media_handle_t *smh);
SWITCH_DECLARE(void) switch_core_media_prepare_codecs(switch_core_session_t *session, switch_bool_t force);
SWITCH_DECLARE(void) switch_core_media_start_udptl(switch_core_session_t *session, switch_t38_options_t *t38_options);
SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg);
@ -254,6 +256,7 @@ SWITCH_DECLARE(void) switch_core_media_init(void);
SWITCH_DECLARE(void) switch_core_media_deinit(void);
SWITCH_DECLARE(void) switch_core_media_set_stats(switch_core_session_t *session);
SWITCH_DECLARE(void) switch_core_session_wake_video_thread(switch_core_session_t *session);
SWITCH_DECLARE(void) switch_core_session_clear_crypto(switch_core_session_t *session);
SWITCH_END_EXTERN_C
#endif

View File

@ -309,10 +309,11 @@ SWITCH_DECLARE(switch_status_t) switch_event_free_subclass_detailed(const char *
\return SWITCH_STATUS_SUCCESS if the operation was successful
\note you must free the resulting string when you are finished with it
*/
SWITCH_DECLARE(switch_status_t) switch_event_binary_deserialize(switch_event_t **eventp, void **data, switch_size_t len, switch_bool_t destroy);
SWITCH_DECLARE(switch_status_t) switch_event_binary_deserialize(switch_event_t **eventp, void **data, switch_size_t len, switch_bool_t duplicate);
SWITCH_DECLARE(switch_status_t) switch_event_binary_serialize(switch_event_t *event, void **data, switch_size_t *len);
SWITCH_DECLARE(switch_status_t) switch_event_serialize(switch_event_t *event, char **str, switch_bool_t encode);
SWITCH_DECLARE(switch_status_t) switch_event_serialize_json(switch_event_t *event, char **str);
SWITCH_DECLARE(switch_status_t) switch_event_serialize_json_obj(switch_event_t *event, cJSON **json);
SWITCH_DECLARE(switch_status_t) switch_event_create_json(switch_event_t **event, const char *json);
SWITCH_DECLARE(switch_status_t) switch_event_create_brackets(char *data, char a, char b, char c, switch_event_t **event, char **new_data, switch_bool_t dup);
SWITCH_DECLARE(switch_status_t) switch_event_create_array_pair(switch_event_t **event, char **names, char **vals, int len);
@ -420,8 +421,38 @@ SWITCH_DECLARE(void) switch_event_deliver(switch_event_t **event);
SWITCH_DECLARE(char *) switch_event_build_param_string(switch_event_t *event, const char *prefix, switch_hash_t *vars_map);
SWITCH_DECLARE(int) switch_event_check_permission_list(switch_event_t *list, const char *name);
SWITCH_DECLARE(void) switch_event_add_presence_data_cols(switch_channel_t *channel, switch_event_t *event, const char *prefix);
SWITCH_DECLARE(void) switch_json_add_presence_data_cols(switch_event_t *event, cJSON *json, const char *prefix);
SWITCH_DECLARE(void) switch_event_launch_dispatch_threads(uint32_t max);
SWITCH_DECLARE(uint32_t) switch_event_channel_broadcast(const char *event_channel, cJSON **json, const char *key, switch_event_channel_id_t id);
SWITCH_DECLARE(uint32_t) switch_event_channel_unbind(const char *event_channel, switch_event_channel_func_t func);
SWITCH_DECLARE(switch_status_t) switch_event_channel_bind(const char *event_channel, switch_event_channel_func_t func, switch_event_channel_id_t *id);
typedef void (*switch_live_array_command_handler_t)(switch_live_array_t *la, const char *cmd, const char *sessid, cJSON *jla, void *user_data);
#define NO_EVENT_CHANNEL_ID 0
#define SWITCH_EVENT_CHANNEL_GLOBAL "__global__"
SWITCH_DECLARE(switch_status_t) switch_live_array_clear(switch_live_array_t *la);
SWITCH_DECLARE(switch_status_t) switch_live_array_bootstrap(switch_live_array_t *la, const char *sessid, switch_event_channel_id_t channel_id);
SWITCH_DECLARE(switch_status_t) switch_live_array_destroy(switch_live_array_t **live_arrayP);
SWITCH_DECLARE(switch_status_t) switch_live_array_create(const char *event_channel, const char *name,
switch_event_channel_id_t channel_id, switch_live_array_t **live_arrayP);
SWITCH_DECLARE(cJSON *) switch_live_array_get(switch_live_array_t *la, const char *name);
SWITCH_DECLARE(cJSON *) switch_live_array_get_idx(switch_live_array_t *la, int idx);
SWITCH_DECLARE(switch_status_t) switch_live_array_del(switch_live_array_t *la, const char *name);
SWITCH_DECLARE(switch_status_t) switch_live_array_add(switch_live_array_t *la, const char *name, int index, cJSON **obj, switch_bool_t destroy);
SWITCH_DECLARE(switch_status_t) switch_live_array_visible(switch_live_array_t *la, switch_bool_t visible, switch_bool_t force);
SWITCH_DECLARE(switch_bool_t) switch_live_array_isnew(switch_live_array_t *la);
SWITCH_DECLARE(void) switch_live_array_lock(switch_live_array_t *la);
SWITCH_DECLARE(void) switch_live_array_unlock(switch_live_array_t *la);
SWITCH_DECLARE(void) switch_live_array_set_user_data(switch_live_array_t *la, void *user_data);
SWITCH_DECLARE(void) switch_live_array_set_command_handler(switch_live_array_t *la, switch_live_array_command_handler_t command_handler);
SWITCH_DECLARE(void) switch_live_array_parse_json(cJSON *json, switch_event_channel_id_t channel_id);
///\}
SWITCH_END_EXTERN_C

View File

@ -76,7 +76,8 @@ SWITCH_DECLARE(int) cJSON_GetArraySize(cJSON *array);
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
SWITCH_DECLARE(cJSON *)cJSON_GetArrayItem(cJSON *array,int item);
/* Get item "string" from object. Case insensitive. */
SWITCH_DECLARE(cJSON *)cJSON_GetObjectItem(cJSON *object,const char *string);
SWITCH_DECLARE(cJSON *)cJSON_GetObjectItem(const cJSON *object,const char *string);
SWITCH_DECLARE(const char *)cJSON_GetObjectCstr(const cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
SWITCH_DECLARE(const char *)cJSON_GetErrorPtr(void);
@ -127,6 +128,55 @@ SWITCH_DECLARE(cJSON *) cJSON_Duplicate(cJSON *item,int recurse);
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
SWITCH_DECLARE(cJSON *) cJSON_CreateStringPrintf(const char *fmt, ...);
static inline cJSON *json_add_child_obj(cJSON *json, const char *name, cJSON *obj)
{
cJSON *new_json = NULL;
switch_assert(json);
if (obj) {
new_json = obj;
} else {
new_json = cJSON_CreateObject();
}
switch_assert(new_json);
cJSON_AddItemToObject(json, name, new_json);
return new_json;
}
static inline cJSON *json_add_child_array(cJSON *json, const char *name)
{
cJSON *new_json = NULL;
switch_assert(json);
new_json = cJSON_CreateArray();
switch_assert(new_json);
cJSON_AddItemToObject(json, name, new_json);
return new_json;
}
static inline cJSON *json_add_child_string(cJSON *json, const char *name, const char *val)
{
cJSON *new_json = NULL;
switch_assert(json);
new_json = cJSON_CreateString(val);
switch_assert(new_json);
cJSON_AddItemToObject(json, name, new_json);
return new_json;
}
#ifdef __cplusplus
}
#endif

View File

@ -69,6 +69,8 @@ SWITCH_BEGIN_EXTERN_C
switch_chat_application_interface_t *chat_application_interface;
/*! the table of api functions the module has implemented */
switch_api_interface_t *api_interface;
/*! the table of json api functions the module has implemented */
switch_json_api_interface_t *json_api_interface;
/*! the table of file formats the module has implemented */
switch_file_interface_t *file_interface;
/*! the table of speech interfaces the module has implemented */
@ -189,6 +191,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_execute_chat_app(switch_event_t *mes
*/
SWITCH_DECLARE(switch_api_interface_t *) switch_loadable_module_get_api_interface(const char *name);
/*!
\brief Retrieve the JSON API interface by it's registered name
\param name the name of the API
\return the desired API interface
*/
SWITCH_DECLARE(switch_json_api_interface_t *) switch_loadable_module_get_json_api_interface(const char *name);
/*!
\brief Retrieve the file format interface by it's registered name
\param name the name of the file format
@ -275,6 +284,16 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_
*/
SWITCH_DECLARE(switch_status_t) switch_api_execute(const char *cmd, const char *arg, switch_core_session_t *session, switch_stream_handle_t *stream);
/*!
\brief Execute a registered JSON API command
\param json the name of the JSON API command to execute
\param arg the optional arguement to the command
\param session an optional session
\param stream stream for output
\return the status returned by the API call
*/
SWITCH_DECLARE(switch_status_t) switch_json_api_execute(cJSON *json, switch_core_session_t *session, cJSON **retval);
/*!
\brief Load a module
\param dir the directory where the module resides
@ -328,6 +347,16 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_shutdown(void);
break; \
}
#define SWITCH_ADD_JSON_API(json_api_int, int_name, descript, funcptr, syntax_string) \
for (;;) { \
json_api_int = (switch_json_api_interface_t *)switch_loadable_module_create_interface(*module_interface, SWITCH_JSON_API_INTERFACE); \
json_api_int->interface_name = int_name; \
json_api_int->desc = descript; \
json_api_int->function = funcptr; \
json_api_int->syntax = syntax_string; \
break; \
}
#define SWITCH_ADD_CHAT(chat_int, int_name, funcptr) \
for (;;) { \
chat_int = (switch_chat_interface_t *)switch_loadable_module_create_interface(*module_interface, SWITCH_CHAT_INTERFACE); \
@ -510,8 +539,9 @@ static inline switch_bool_t switch_core_codec_ready(switch_codec_t *codec)
}
SWITCH_DECLARE(switch_core_recover_callback_t) switch_core_get_secondary_recover_callback(const char *key);
SWITCH_DECLARE(switch_status_t) switch_core_register_secondary_recover_callback(const char *key, switch_core_recover_callback_t cb);
SWITCH_DECLARE(void) switch_core_unregister_secondary_recover_callback(const char *key);
SWITCH_END_EXTERN_C
#endif

View File

@ -743,6 +743,24 @@ struct switch_api_interface {
struct switch_api_interface *next;
};
/*! \brief A module interface to implement a json api function */
struct switch_json_api_interface {
/*! the name of the interface */
const char *interface_name;
/*! a description of the api function */
const char *desc;
/*! function the api call uses */
switch_json_api_function_t function;
/*! an example of the api syntax */
const char *syntax;
switch_thread_rwlock_t *rwlock;
int refs;
switch_mutex_t *reflock;
switch_loadable_module_interface_t *parent;
struct switch_json_api_interface *next;
};
#define PROTECT_INTERFACE(_it) if (_it) {switch_mutex_lock(_it->reflock); switch_thread_rwlock_rdlock(_it->parent->rwlock); switch_thread_rwlock_rdlock(_it->rwlock); _it->refs++; _it->parent->refs++; switch_mutex_unlock(_it->reflock);} //if (!strcmp(_it->interface_name, "user")) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "+++++++++++LOCK %s %d/%d\n", _it->interface_name, _it->refs, _it->parent->refs);
#define UNPROTECT_INTERFACE(_it) if (_it) {switch_mutex_lock(_it->reflock); switch_thread_rwlock_unlock(_it->rwlock); switch_thread_rwlock_unlock(_it->parent->rwlock); _it->refs--; _it->parent->refs--; switch_mutex_unlock(_it->reflock);} //if (!strcmp(_it->interface_name, "user")) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "---------UNLOCK %s %d/%d\n", _it->interface_name, _it->refs, _it->parent->refs);

View File

@ -508,6 +508,7 @@ SWITCH_DECLARE(switch_byte_t) switch_rtp_check_auto_adj(switch_rtp_t *rtp_sessio
SWITCH_DECLARE(void) switch_rtp_set_interdigit_delay(switch_rtp_t *rtp_session, uint32_t delay);
SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, dtls_fingerprint_t *local_fp, dtls_fingerprint_t *remote_fp, dtls_type_t type);
SWITCH_DECLARE(switch_status_t) switch_rtp_del_dtls(switch_rtp_t *rtp_session, dtls_type_t type);
SWITCH_DECLARE(int) switch_rtp_has_dtls(void);
SWITCH_DECLARE(void) switch_rtp_video_refresh(switch_rtp_t *rtp_session);

View File

@ -38,6 +38,7 @@
#define SWITCH_TYPES_H
#include <switch.h>
#include <switch_json.h>
SWITCH_BEGIN_EXTERN_C
#define SWITCH_ENT_ORIGINATE_DELIM ":_:"
@ -223,8 +224,16 @@ SWITCH_BEGIN_EXTERN_C
#define SWITCH_DEFAULT_FILE_BUFFER_LEN 65536
#define SWITCH_DTMF_LOG_LEN 1000
#define SWITCH_MAX_TRANS 2000
#define SWITCH_CORE_SESSION_MAX_PRIVATES 2
typedef uint8_t switch_byte_t;
typedef enum {
SWITCH_PVT_PRIMARY = 0,
SWITCH_PVT_SECONDARY
} switch_pvt_class_t;
/*!
\enum switch_dtmf_source_t
\brief DTMF sources
@ -357,7 +366,8 @@ typedef enum {
SWITCH_ASR_INTERFACE,
SWITCH_MANAGEMENT_INTERFACE,
SWITCH_LIMIT_INTERFACE,
SWITCH_CHAT_APPLICATION_INTERFACE
SWITCH_CHAT_APPLICATION_INTERFACE,
SWITCH_JSON_API_INTERFACE,
} switch_module_interface_name_t;
typedef enum {
@ -653,6 +663,7 @@ typedef enum {
SWITCH_RTP_FLAG_ENABLE_RTCP,
SWITCH_RTP_FLAG_RTCP_MUX,
SWITCH_RTP_FLAG_KILL_JB,
SWITCH_RTP_FLAG_VIDEO_BREAK,
SWITCH_RTP_FLAG_INVALID
} switch_rtp_flag_t;
@ -2000,6 +2011,7 @@ typedef struct switch_codec_interface switch_codec_interface_t;
typedef struct switch_application_interface switch_application_interface_t;
typedef struct switch_chat_application_interface switch_chat_application_interface_t;
typedef struct switch_api_interface switch_api_interface_t;
typedef struct switch_json_api_interface switch_json_api_interface_t;
typedef struct switch_file_interface switch_file_interface_t;
typedef struct switch_speech_interface switch_speech_interface_t;
typedef struct switch_asr_interface switch_asr_interface_t;
@ -2083,6 +2095,12 @@ typedef switch_status_t (*switch_api_function_t) (_In_opt_z_ const char *cmd, _I
#define SWITCH_STANDARD_API(name) static switch_status_t name (_In_opt_z_ const char *cmd, _In_opt_ switch_core_session_t *session, _In_ switch_stream_handle_t *stream)
typedef switch_status_t (*switch_json_api_function_t) (const cJSON *json, _In_opt_ switch_core_session_t *session, cJSON **json_reply);
#define SWITCH_STANDARD_JSON_API(name) static switch_status_t name (const cJSON *json, _In_opt_ switch_core_session_t *session, cJSON **json_reply)
typedef switch_status_t (*switch_input_callback_function_t) (switch_core_session_t *session, void *input,
switch_input_type_t input_type, void *buf, unsigned int buflen);
typedef switch_status_t (*switch_read_frame_callback_function_t) (switch_core_session_t *session, switch_frame_t *frame, void *user_data);
@ -2236,6 +2254,13 @@ struct sql_queue_manager;
struct switch_media_handle_s;
typedef struct switch_media_handle_s switch_media_handle_t;
typedef uint32_t switch_event_channel_id_t;
typedef void (*switch_event_channel_func_t)(const char *event_channel, cJSON *json, const char *key, switch_event_channel_id_t id);
struct switch_live_array_s;
typedef struct switch_live_array_s switch_live_array_t;
SWITCH_END_EXTERN_C
#endif

View File

@ -297,9 +297,6 @@ static switch_status_t channel_on_init(switch_core_session_t *session)
switch_set_flag_locked(tech_pvt, TFLAG_IO);
/* Move channel's state machine to ROUTING */
switch_channel_set_state(channel, CS_ROUTING);
return SWITCH_STATUS_SUCCESS;
}

View File

@ -1916,6 +1916,7 @@ static switch_status_t channel_on_init(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
struct private_object *tech_pvt = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS;
tech_pvt = switch_core_session_get_private(session);
switch_assert(tech_pvt != NULL);
@ -1928,11 +1929,10 @@ static switch_status_t channel_on_init(switch_core_session_t *session)
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
switch_channel_mark_answered(channel);
}
/* Move channel's state machine to ROUTING */
switch_channel_set_state(channel, CS_ROUTING);
status = SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_SUCCESS;
return status;
}
static switch_status_t channel_on_routing(switch_core_session_t *session)

View File

@ -586,11 +586,6 @@ static switch_status_t channel_on_init(switch_core_session_t *session)
//ERRORA("%s CHANNEL INIT\n", GSMOPEN_P_LOG, tech_pvt->name);
switch_set_flag(tech_pvt, TFLAG_IO);
/* Move channel's state machine to ROUTING. This means the call is trying
to get from the initial start where the call because, to the point
where a destination has been identified. If the channel is simply
left in the initial state, nothing will happen. */
switch_channel_set_state(channel, CS_ROUTING);
switch_mutex_lock(globals.mutex);
globals.calls++;

View File

@ -416,11 +416,6 @@ static switch_status_t channel_on_init(switch_core_session_t *session)
switch_set_flag(tech_pvt, TFLAG_IO);
switch_mutex_unlock(tech_pvt->flag_mutex);
/* Move channel's state machine to ROUTING. This means the call is trying
to get from the initial start where the call because, to the point
where a destination has been identified. If the channel is simply
left in the initial state, nothing will happen. */
switch_channel_set_state(channel, CS_ROUTING);
switch_mutex_lock(globals.mutex);
globals.calls++;

View File

@ -1655,7 +1655,6 @@ switch_status_t FSH323Connection::on_init()
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"Started routing for connection [%p]\n",this);
switch_channel_set_state(channel, CS_ROUTING);
return SWITCH_STATUS_SUCCESS;
}

View File

@ -231,6 +231,7 @@ static switch_status_t channel_on_init(switch_core_session_t *session)
switch_caller_profile_t *caller_profile;
switch_event_t *vars = NULL;
const char *var;
switch_status_t status = SWITCH_STATUS_FALSE;
tech_pvt = switch_core_session_get_private(session);
switch_assert(tech_pvt != NULL);
@ -354,11 +355,12 @@ static switch_status_t channel_on_init(switch_core_session_t *session)
}
switch_channel_set_variable(channel, "loopback_leg", switch_test_flag(tech_pvt, TFLAG_BLEG) ? "B" : "A");
status = SWITCH_STATUS_SUCCESS;
switch_channel_set_state(channel, CS_ROUTING);
end:
return SWITCH_STATUS_SUCCESS;
return status;
}
static void do_reset(loopback_private_t *tech_pvt)

View File

@ -853,7 +853,7 @@ switch_status_t FSConnection::on_init()
return SWITCH_STATUS_FALSE;
PTRACE(4, "mod_opal\tStarted routing for connection " << *this);
switch_channel_set_state(m_fsChannel, CS_ROUTING);
return SWITCH_STATUS_SUCCESS;
}

View File

@ -282,11 +282,6 @@ SWITCH_STANDARD_API(pa_cmd);
*/
static switch_status_t channel_on_init(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
/* Move channel's state machine to ROUTING */
switch_channel_set_state(channel, CS_ROUTING);
return SWITCH_STATUS_SUCCESS;
}

View File

@ -141,11 +141,6 @@ static switch_status_t channel_on_init(switch_core_session_t *session)
assert(channel != NULL);
switch_set_flag_locked(tech_pvt, TFLAG_IO);
/* Move channel's state machine to ROUTING. This means the call is trying
to get from the initial start where the call because, to the point
where a destination has been identified. If the channel is simply
left in the initial state, nothing will happen. */
switch_channel_set_state(channel, CS_ROUTING);
switch_mutex_lock(globals.mutex);
globals.calls++;
switch_mutex_unlock(globals.mutex);

View File

@ -163,13 +163,6 @@ switch_status_t rtmp_on_init(switch_core_session_t *session)
switch_set_flag_locked(tech_pvt, TFLAG_IO);
/* Move channel's state machine to ROUTING. This means the call is trying
to get from the initial start where the call because, to the point
where a destination has been identified. If the channel is simply
left in the initial state, nothing will happen. */
switch_channel_set_state(channel, CS_ROUTING);
switch_mutex_lock(rsession->profile->mutex);
rsession->profile->calls++;
switch_mutex_unlock(rsession->profile->mutex);

View File

@ -648,7 +648,8 @@ switch_status_t channel_on_init(switch_core_session_t *session)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL INIT\n", switch_channel_get_name(channel));
return SWITCH_STATUS_SUCCESS;
/* 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*/
return SWITCH_STATUS_FALSE;
}
struct channel_on_routing_helper {

View File

@ -457,11 +457,6 @@ static switch_status_t channel_on_init(switch_core_session_t *session)
switch_set_flag(tech_pvt, TFLAG_IO);
switch_mutex_unlock(tech_pvt->flag_mutex);
/* Move channel's state machine to ROUTING. This means the call is trying
to get from the initial start where the call because, to the point
where a destination has been identified. If the channel is simply
left in the initial state, nothing will happen. */
switch_channel_set_state(channel, CS_ROUTING);
DEBUGA_SKYPE("%s CHANNEL INIT %s\n", SKYPOPEN_P_LOG, tech_pvt->name, switch_core_session_get_uuid(session));
switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(session), sizeof(tech_pvt->session_uuid_str));
@ -670,11 +665,11 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session)
static switch_status_t channel_on_routing(switch_core_session_t *session)
{
switch_channel_t *channel = NULL;
//switch_channel_t *channel = NULL;
private_t *tech_pvt = NULL;
channel = switch_core_session_get_channel(session);
switch_assert(channel != NULL);
//channel = switch_core_session_get_channel(session);
//switch_assert(channel != NULL);
tech_pvt = switch_core_session_get_private(session);
switch_assert(tech_pvt != NULL);

View File

@ -102,20 +102,6 @@ static switch_status_t sofia_on_init(switch_core_session_t *session)
}
}
if (switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING_BRIDGE)) {
switch_channel_set_state(channel, CS_RESET);
} else {
if (switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING)) {
switch_channel_set_state(channel, CS_EXECUTE);
} else {
/* Move channel's state machine to ROUTING */
switch_channel_set_state(channel, CS_ROUTING);
assert(switch_channel_get_state(channel) != CS_INIT);
}
}
end:
switch_mutex_unlock(tech_pvt->sofia_mutex);
@ -156,43 +142,6 @@ static switch_status_t sofia_on_reset(switch_core_session_t *session)
switch_channel_get_name(switch_core_session_get_channel(session)));
if (switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING_BRIDGE)) {
switch_core_session_t *other_session = NULL;
const char *uuid = switch_core_session_get_uuid(session);
if (switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) {
const char *other_uuid = switch_channel_get_partner_uuid(channel);
int x = 0;
if (other_uuid) {
for (x = 0; other_session == NULL && x < 20; x++) {
if (!switch_channel_up(channel)) {
break;
}
other_session = switch_core_session_locate(other_uuid);
switch_yield(100000);
}
}
if (other_session) {
switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
switch_channel_clear_flag(channel, CF_BRIDGE_ORIGINATOR);
switch_channel_wait_for_state_timeout(other_channel, CS_RESET, 5000);
switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 2000, NULL);
if (switch_channel_test_flag(channel, CF_PROXY_MODE) && switch_channel_test_flag(other_channel, CF_PROXY_MODE)) {
switch_ivr_signal_bridge(session, other_session);
} else {
switch_ivr_uuid_bridge(uuid, other_uuid);
}
switch_core_session_rwunlock(other_session);
}
}
switch_channel_clear_flag(tech_pvt->channel, CF_RECOVERING_BRIDGE);
}
return SWITCH_STATUS_SUCCESS;
}
@ -221,12 +170,11 @@ static switch_status_t sofia_on_execute(switch_core_session_t *session)
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_assert(tech_pvt != NULL);
switch_channel_clear_flag(tech_pvt->channel, CF_RECOVERING);
if (!sofia_test_flag(tech_pvt, TFLAG_HOLD_LOCK)) {
sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
switch_channel_clear_flag(channel, CF_LEG_HOLDING);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SOFIA EXECUTE\n",
switch_channel_get_name(switch_core_session_get_channel(session)));
@ -873,8 +821,6 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
tech_pvt->session_refresher = nua_no_refresher;
}
if (sofia_use_soa(tech_pvt)) {
nua_respond(tech_pvt->nh, SIP_200_OK,
NUTAG_AUTOANSWER(0),

View File

@ -300,7 +300,7 @@ static switch_status_t channel_on_init(switch_core_session_t *session)
switch_channel_set_state(channel, CS_CONSUME_MEDIA);
return SWITCH_STATUS_SUCCESS;
return SWITCH_STATUS_FALSE;
}
static switch_status_t channel_on_destroy(switch_core_session_t *session)

View File

@ -1907,9 +1907,6 @@ int sofia_recover_callback(switch_core_session_t *session)
switch_channel_get_name(channel), use_uuid);
}
}
switch_core_media_recover_session(session);
}
r++;

View File

@ -850,11 +850,6 @@ static switch_status_t unicall_on_init(switch_core_session_t *session)
switch_set_flag_locked(tech_pvt, TFLAG_IO);
/* Move channel's state machine to ROUTING. This means the call is trying
to get from the initial state to the point where a destination has been
identified. If the channel is simply left in the initial state, nothing
will happen. */
switch_channel_set_state(channel, CS_ROUTING);
switch_mutex_lock(globals.mutex);
globals.calls++;
switch_mutex_unlock(globals.mutex);

View File

@ -385,6 +385,13 @@ SWITCH_DECLARE(switch_channel_timetable_t *) switch_channel_get_timetable(switch
return times;
}
SWITCH_DECLARE(void) switch_channel_set_direction(switch_channel_t *channel, switch_call_direction_t direction)
{
if (!switch_core_session_in_thread(channel->session)) {
channel->direction = direction;
}
}
SWITCH_DECLARE(switch_call_direction_t) switch_channel_direction(switch_channel_t *channel)
{
return channel->direction;
@ -491,6 +498,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *chan
switch_zmalloc(dt, sizeof(*dt));
*dt = new_dtmf;
while (switch_queue_trypush(channel->dtmf_queue, dt) != SWITCH_STATUS_SUCCESS) {
if (switch_queue_trypop(channel->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
free(pop);
@ -509,6 +517,8 @@ SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf(switch_channel_t *chan
switch_mutex_unlock(channel->dtmf_mutex);
switch_core_media_break(channel->session, SWITCH_MEDIA_TYPE_AUDIO);
return status;
}
@ -2951,19 +2961,33 @@ SWITCH_DECLARE(void) switch_channel_invert_cid(switch_channel_t *channel)
SWITCH_DECLARE(void) switch_channel_flip_cid(switch_channel_t *channel)
{
switch_event_t *event;
const char *tmp = NULL;
switch_mutex_lock(channel->profile_mutex);
if (channel->caller_profile->callee_id_name) {
tmp = channel->caller_profile->caller_id_name;
switch_channel_set_variable(channel, "pre_transfer_caller_id_name", channel->caller_profile->caller_id_name);
channel->caller_profile->caller_id_name = switch_core_strdup(channel->caller_profile->pool, channel->caller_profile->callee_id_name);
}
channel->caller_profile->callee_id_name = SWITCH_BLANK_STRING;
if (switch_channel_test_flag(channel, CF_BRIDGED)) {
channel->caller_profile->callee_id_name = SWITCH_BLANK_STRING;
} else if (tmp) {
channel->caller_profile->callee_id_name = tmp;
}
if (channel->caller_profile->callee_id_number) {
tmp = channel->caller_profile->caller_id_number;
switch_channel_set_variable(channel, "pre_transfer_caller_id_number", channel->caller_profile->caller_id_number);
channel->caller_profile->caller_id_number = switch_core_strdup(channel->caller_profile->pool, channel->caller_profile->callee_id_number);
}
channel->caller_profile->callee_id_number = SWITCH_BLANK_STRING;
if (switch_channel_test_flag(channel, CF_BRIDGED)) {
channel->caller_profile->callee_id_number = SWITCH_BLANK_STRING;
} else if (tmp) {
channel->caller_profile->callee_id_number = tmp;
}
switch_mutex_unlock(channel->profile_mutex);
@ -3260,7 +3284,7 @@ static void check_secure(switch_channel_t *channel)
{
const char *var, *sec;
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
if (!switch_channel_media_ready(channel) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
if ((sec = switch_channel_get_variable(channel, "rtp_secure_media")) && switch_true(sec)) {
if (!(var = switch_channel_get_variable(channel, "rtp_has_crypto"))) {
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "rtp_secure_media invalid in this context.\n");

View File

@ -171,8 +171,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_set_real_read_codec(switch_c
}
switch_channel_set_variable(channel, "read_codec", session->read_impl.iananame);
switch_channel_set_variable(channel, "original_read_codec", session->read_impl.iananame);
switch_snprintf(tmp, sizeof(tmp), "%d", session->read_impl.actual_samples_per_second);
switch_channel_set_variable(channel, "read_rate", tmp);
switch_channel_set_variable(channel, "original_read_rate", tmp);
session->raw_read_frame.codec = session->read_codec;
session->raw_write_frame.codec = session->read_codec;

View File

@ -638,8 +638,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n");
goto done;
default:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s decoder error!\n",
session->read_codec->codec_interface->interface_name);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s decoder error! [%d]\n",
session->read_codec->codec_interface->interface_name, status);
goto done;
}
}

View File

@ -509,6 +509,31 @@ SWITCH_DECLARE(const char *)switch_core_media_get_codec_string(switch_core_sessi
return !zstr(preferred) ? preferred : fallback;
}
SWITCH_DECLARE(void) switch_core_session_clear_crypto(switch_core_session_t *session)
{
int i;
switch_media_handle_t *smh;
const char *vars[] = { "rtp_last_audio_local_crypto_key",
"srtp_remote_audio_crypto_key",
"srtp_remote_audio_crypto_tag",
"srtp_remote_video_crypto_key",
"srtp_remote_video_crypto_tag",
"rtp_secure_media",
NULL};
for(i = 0; vars[i] ;i++) {
switch_channel_set_variable(session->channel, vars[i], NULL);
}
if (!(smh = session->media_handle)) {
return;
}
memset(&smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec, 0, sizeof(smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec));
memset(&smh->engines[SWITCH_MEDIA_TYPE_VIDEO].ssec, 0, sizeof(smh->engines[SWITCH_MEDIA_TYPE_VIDEO].ssec));
}
SWITCH_DECLARE(const char *) switch_core_session_local_crypto_key(switch_core_session_t *session, switch_media_type_t type)
{
@ -1036,15 +1061,23 @@ SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t
*smhp = NULL;
if (zstr(params->sdp_username)) {
params->sdp_username = "FreeSWITCH";
}
if ((session->media_handle = switch_core_session_alloc(session, (sizeof(*smh))))) {
session->media_handle->session = session;
*smhp = session->media_handle;
switch_set_flag(session->media_handle, SMF_INIT);
session->media_handle->media_flags[SCMF_RUNNING] = 1;
session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].read_frame.buflen = SWITCH_RTP_MAX_BUF_LEN;
session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].type = SWITCH_MEDIA_TYPE_AUDIO;
session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].read_frame.buflen = SWITCH_RTP_MAX_BUF_LEN;
session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].type = SWITCH_MEDIA_TYPE_VIDEO;
session->media_handle->mparams = params;
switch_mutex_init(&session->media_handle->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].ssrc =
@ -1098,18 +1131,18 @@ SWITCH_DECLARE(int32_t) switch_media_handle_test_media_flag(switch_media_handle_
SWITCH_DECLARE(switch_status_t) switch_core_session_media_handle_ready(switch_core_session_t *session)
{
if (session->media_handle && switch_test_flag(session->media_handle, SMF_INIT)) {
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
SWITCH_DECLARE(switch_media_handle_t *) switch_core_session_get_media_handle(switch_core_session_t *session)
{
if (switch_core_session_media_handle_ready(session)) {
if (switch_core_session_media_handle_ready(session) == SWITCH_STATUS_SUCCESS) {
return session->media_handle;
}
@ -1125,6 +1158,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_clear_media_handle(switch_co
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_core_media_params_t *) switch_core_media_get_mparams(switch_media_handle_t *smh)
{
switch_assert(smh);
return smh->mparams;
}
SWITCH_DECLARE(void) switch_core_media_prepare_codecs(switch_core_session_t *session, switch_bool_t force)
{
@ -1753,8 +1791,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_se
switch_core_session_set_video_write_codec(session, &v_engine->write_codec);
switch_channel_set_variable_printf(session->channel, "rtp_last_video_codec_string", "%s@%dh@%di",
v_engine->codec_params.iananame, v_engine->codec_params.rm_rate, v_engine->codec_params.codec_ms);
switch_channel_set_variable_printf(session->channel, "rtp_last_video_codec_string", "%s@%dh",
v_engine->codec_params.rm_encoding, v_engine->codec_params.rm_rate);
if (switch_rtp_ready(v_engine->rtp_session)) {
@ -2018,12 +2056,26 @@ static int dtls_ok(switch_core_session_t *session)
#pragma warning(disable:4702)
#endif
//?
SWITCH_DECLARE(switch_call_direction_t) switch_ice_direction(switch_core_session_t *session)
{
switch_call_direction_t r = switch_channel_direction(session->channel);
if ((switch_channel_test_flag(session->channel, CF_REINVITE) || switch_channel_test_flag(session->channel, CF_RECOVERING))
&& switch_channel_test_flag(session->channel, CF_WEBRTC)) {
r = SWITCH_CALL_DIRECTION_OUTBOUND;
}
return r;
}
//?
static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_session_t *sdp, sdp_media_t *m)
{
switch_rtp_engine_t *engine = &smh->engines[type];
sdp_attribute_t *attr;
int i = 0, got_rtcp_mux = 0;
const char *val;
if (engine->ice_in.chosen[0] && engine->ice_in.chosen[1] && !switch_channel_test_flag(smh->session->channel, CF_REINVITE)) {
return;
@ -2078,6 +2130,12 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
} else if (!engine->remote_ssrc && !strcasecmp(attr->a_name, "ssrc") && attr->a_value) {
engine->remote_ssrc = (uint32_t) atol(attr->a_value);
if (engine->rtp_session && engine->remote_ssrc) {
switch_rtp_set_remote_ssrc(engine->rtp_session, engine->remote_ssrc);
}
#ifdef RTCP_MUX
} else if (!strcasecmp(attr->a_name, "rtcp-mux")) {
engine->rtcp_mux = SWITCH_TRUE;
@ -2139,7 +2197,8 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
engine->ice_in.cands[engine->ice_in.cand_idx][cid].priority = atol(fields[3]);
engine->ice_in.cands[engine->ice_in.cand_idx][cid].con_addr = switch_core_session_strdup(smh->session, fields[4]);
engine->ice_in.cands[engine->ice_in.cand_idx][cid].con_port = (switch_port_t)atoi(fields[5]);
j = 6;
while(j < argc && fields[j+1]) {
@ -2155,6 +2214,7 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
j += 2;
}
if (engine->ice_in.chosen[cid]) {
engine->ice_in.cands[engine->ice_in.chosen[cid]][cid].ready++;
@ -2206,6 +2266,19 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
}
}
/* Got RTP but not RTCP, probably mux */
if (engine->ice_in.chosen[0] && !engine->ice_in.chosen[1] && got_rtcp_mux) {
engine->ice_in.chosen[1] = engine->ice_in.chosen[0];
memcpy(&engine->ice_in.cands[engine->ice_in.chosen[1]][1], &engine->ice_in.cands[engine->ice_in.chosen[0]][0],
sizeof(engine->ice_in.cands[engine->ice_in.chosen[0]][0]));
engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE,
"No %s RTCP candidate found; defaulting to the same as RTP [%s:%d]\n", type2str(type),
engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr, engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port);
}
/* look for any candidates and hope for auto-adjust */
if (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]) {
for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]); i++) {
@ -2246,7 +2319,9 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
engine->codec_params.remote_sdp_ip = switch_core_session_strdup(smh->session, (char *) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr);
engine->codec_params.remote_sdp_port = (switch_port_t) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port;
if (engine->remote_rtcp_port) {
engine->remote_rtcp_port = engine->codec_params.remote_sdp_port;
}
switch_snprintf(tmp, sizeof(tmp), "%d", engine->codec_params.remote_sdp_port);
switch_channel_set_variable(smh->session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, engine->codec_params.remote_sdp_ip);
@ -2271,6 +2346,7 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
if (switch_channel_test_flag(smh->session->channel, CF_REINVITE)) {
if (switch_rtp_ready(engine->rtp_session) && engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "RE-Activating %s ICE\n", type2str(type));
@ -2284,7 +2360,7 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
ICE_GOOGLE_JINGLE,
NULL
#else
switch_channel_direction(smh->session->channel) ==
switch_ice_direction(smh->session) ==
SWITCH_CALL_DIRECTION_OUTBOUND ? ICE_VANILLA : (ICE_VANILLA | ICE_CONTROLLED),
&engine->ice_in
#endif
@ -2295,7 +2371,37 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
}
if (engine->rtp_session && ((val = switch_channel_get_variable(smh->session->channel,
type == SWITCH_MEDIA_TYPE_VIDEO ?
"rtcp_video_interval_msec" : "rtcp_audio_interval_msec"))
|| (val = type == SWITCH_MEDIA_TYPE_VIDEO ?
smh->mparams->rtcp_video_interval_msec : smh->mparams->rtcp_audio_interval_msec))) {
const char *rport = switch_channel_get_variable(smh->session->channel,
type == SWITCH_MEDIA_TYPE_VIDEO ? "rtp_remote_video_rtcp_port" : "rtp_remote_audio_rtcp_port");
switch_port_t remote_rtcp_port = engine->remote_rtcp_port;
if (!remote_rtcp_port && rport) {
remote_rtcp_port = (switch_port_t)atoi(rport);
}
if (!strcasecmp(val, "passthru")) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "Activating %s RTCP PASSTHRU PORT %d\n",
type2str(type), remote_rtcp_port);
switch_rtp_activate_rtcp(engine->rtp_session, -1, remote_rtcp_port, engine->rtcp_mux > 0);
} else {
int interval = atoi(val);
if (interval < 100 || interval > 500000) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_ERROR,
"Invalid rtcp interval spec [%d] must be between 100 and 500000\n", interval);
interval = 10000;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "Activating %s RTCP PORT %d\n", type2str(type), remote_rtcp_port);
switch_rtp_activate_rtcp(engine->rtp_session, interval, remote_rtcp_port, engine->rtcp_mux > 0);
}
}
if (engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready) {
if (!strcmp(engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr, engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr)
&& engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port == engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port) {
@ -2313,7 +2419,7 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
ICE_GOOGLE_JINGLE,
NULL
#else
switch_channel_direction(smh->session->channel) ==
switch_ice_direction(smh->session) ==
SWITCH_CALL_DIRECTION_OUTBOUND ? ICE_VANILLA : (ICE_VANILLA | ICE_CONTROLLED),
&engine->ice_in
#endif
@ -3350,6 +3456,116 @@ SWITCH_DECLARE(int) switch_core_media_toggle_hold(switch_core_session_t *session
return changed;
}
static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, void *obj)
{
struct media_helper *mh = obj;
switch_core_session_t *session = mh->session;
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_status_t status;
switch_frame_t *read_frame;
switch_media_handle_t *smh;
if (!(smh = session->media_handle)) {
return NULL;
}
switch_core_session_read_lock(session);
mh->up = 1;
switch_mutex_lock(mh->cond_mutex);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread started. Echo is %s\n",
switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off");
switch_core_session_refresh_video(session);
while (switch_channel_up_nosig(channel)) {
if (switch_channel_test_flag(channel, CF_VIDEO_PASSIVE)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread paused. Echo is %s\n",
switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off");
switch_thread_cond_wait(mh->cond, mh->cond_mutex);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread resumed Echo is %s\n",
switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off");
switch_core_session_refresh_video(session);
}
if (switch_channel_test_flag(channel, CF_VIDEO_PASSIVE)) {
continue;
}
if (!switch_channel_media_up(session->channel)) {
switch_yield(10000);
continue;
}
status = switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
if (!SWITCH_READ_ACCEPTABLE(status)) {
switch_cond_next();
continue;
}
if (switch_channel_test_flag(channel, CF_VIDEO_REFRESH_REQ)) {
switch_core_session_refresh_video(session);
switch_channel_clear_flag(channel, CF_VIDEO_REFRESH_REQ);
}
if (switch_test_flag(read_frame, SFF_CNG)) {
continue;
}
if (switch_channel_test_flag(channel, CF_VIDEO_ECHO)) {
switch_core_session_write_video_frame(session, read_frame, SWITCH_IO_FLAG_NONE, 0);
}
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread ended\n", switch_channel_get_name(session->channel));
switch_mutex_unlock(mh->cond_mutex);
switch_core_session_rwunlock(session);
mh->up = 0;
return NULL;
}
static switch_status_t start_video_thread(switch_core_session_t *session)
{
switch_threadattr_t *thd_attr = NULL;
switch_memory_pool_t *pool = switch_core_session_get_pool(session);
switch_rtp_engine_t *v_engine = NULL;
switch_media_handle_t *smh;
if (!(smh = session->media_handle)) {
return SWITCH_STATUS_FALSE;
}
v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
if (v_engine->media_thread) {
return SWITCH_STATUS_FALSE;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "%s Starting Video thread\n", switch_core_session_get_name(session));
switch_rtp_set_default_payload(v_engine->rtp_session, v_engine->codec_params.agreed_pt);
v_engine->mh.session = session;
switch_threadattr_create(&thd_attr, pool);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
switch_thread_cond_create(&v_engine->mh.cond, pool);
switch_mutex_init(&v_engine->mh.cond_mutex, SWITCH_MUTEX_NESTED, pool);
switch_mutex_init(&v_engine->read_mutex, SWITCH_MUTEX_NESTED, pool);
switch_thread_create(&v_engine->media_thread, thd_attr, video_helper_thread, &v_engine->mh, switch_core_session_get_pool(session));
return SWITCH_STATUS_SUCCESS;
}
//?
#define RA_PTR_LEN 512
@ -3470,7 +3686,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_proxy_remote_addr(switch_core_
}
}
if (switch_rtp_set_remote_address(v_engine->rtp_session, v_engine->codec_params.remote_sdp_ip,
v_engine->codec_params.remote_sdp_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", err);
@ -3482,6 +3698,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_proxy_remote_addr(switch_core_
!switch_channel_test_flag(session->channel, CF_WEBRTC)) {
/* Reactivate the NAT buster flag. */
switch_rtp_set_flag(v_engine->rtp_session, SWITCH_RTP_FLAG_AUTOADJ);
start_video_thread(session);
}
if (switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_TIMING) || switch_media_handle_test_media_flag(smh, SCMF_AUTOFIX_PT)) {
v_engine->check_frames = 0;
@ -3735,6 +3953,24 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_choose_port(switch_core_sessio
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_core_media_choose_ports(switch_core_session_t *session, switch_bool_t audio, switch_bool_t video)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
if (audio && (status = switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_AUDIO, 0)) == SWITCH_STATUS_SUCCESS) {
if (video) {
switch_core_media_check_video_codecs(session);
if (switch_channel_test_flag(session->channel, CF_VIDEO_POSSIBLE)) {
switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_VIDEO, 0);
}
}
}
return status;
}
//?
SWITCH_DECLARE(void) switch_core_media_deactivate_rtp(switch_core_session_t *session)
{
@ -3882,85 +4118,28 @@ SWITCH_DECLARE(void) switch_core_session_wake_video_thread(switch_core_session_t
}
}
static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, void *obj)
static void check_dtls_reinvite(switch_core_session_t *session, switch_rtp_engine_t *engine)
{
struct media_helper *mh = obj;
switch_core_session_t *session = mh->session;
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_status_t status;
switch_frame_t *read_frame;
switch_media_handle_t *smh;
if (switch_channel_test_flag(session->channel, CF_REINVITE)) {
if (!(smh = session->media_handle)) {
return NULL;
if (!zstr(engine->local_dtls_fingerprint.str) && switch_rtp_has_dtls() && dtls_ok(session)) {
dtls_type_t xtype, dtype = switch_ice_direction(session) == SWITCH_CALL_DIRECTION_INBOUND ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "RE-SETTING %s DTLS\n", type2str(engine->type));
xtype = DTLS_TYPE_RTP;
if (engine->rtcp_mux > 0) xtype |= DTLS_TYPE_RTCP;
switch_rtp_add_dtls(engine->rtp_session, &engine->local_dtls_fingerprint, &engine->remote_dtls_fingerprint, dtype | xtype);
if (engine->rtcp_mux < 1) {
xtype = DTLS_TYPE_RTCP;
switch_rtp_add_dtls(engine->rtp_session, &engine->local_dtls_fingerprint, &engine->remote_dtls_fingerprint, dtype | xtype);
}
}
}
switch_core_session_read_lock(session);
mh->up = 1;
switch_mutex_lock(mh->cond_mutex);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread started. Echo is %s\n",
switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off");
switch_core_session_refresh_video(session);
while (switch_channel_up_nosig(channel)) {
if (switch_channel_test_flag(channel, CF_VIDEO_PASSIVE)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread paused. Echo is %s\n",
switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off");
switch_thread_cond_wait(mh->cond, mh->cond_mutex);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread resumed Echo is %s\n",
switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off");
switch_core_session_refresh_video(session);
}
if (switch_channel_test_flag(channel, CF_VIDEO_PASSIVE)) {
continue;
}
if (!switch_channel_media_up(session->channel)) {
switch_yield(10000);
continue;
}
status = switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
if (!SWITCH_READ_ACCEPTABLE(status)) {
switch_cond_next();
continue;
}
if (switch_channel_test_flag(channel, CF_VIDEO_REFRESH_REQ)) {
switch_core_session_refresh_video(session);
switch_channel_clear_flag(channel, CF_VIDEO_REFRESH_REQ);
}
if (switch_test_flag(read_frame, SFF_CNG)) {
continue;
}
if (switch_channel_test_flag(channel, CF_VIDEO_ECHO)) {
switch_core_session_write_video_frame(session, read_frame, SWITCH_IO_FLAG_NONE, 0);
}
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread ended\n", switch_channel_get_name(session->channel));
switch_mutex_unlock(mh->cond_mutex);
switch_core_session_rwunlock(session);
mh->up = 0;
return NULL;
}
//?
SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_session_t *session)
@ -4151,6 +4330,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
switch_rtp_set_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_AUTOADJ);
}
}
if (session && a_engine) {
check_dtls_reinvite(session, a_engine);
}
goto video;
}
@ -4278,7 +4462,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
ICE_GOOGLE_JINGLE,
NULL
#else
switch_channel_direction(session->channel) ==
switch_ice_direction(session) ==
SWITCH_CALL_DIRECTION_OUTBOUND ? ICE_VANILLA : (ICE_VANILLA | ICE_CONTROLLED),
&a_engine->ice_in
#endif
@ -4331,7 +4515,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
ICE_GOOGLE_JINGLE,
NULL
#else
switch_channel_direction(session->channel) ==
switch_ice_direction(session) ==
SWITCH_CALL_DIRECTION_OUTBOUND ? ICE_VANILLA : (ICE_VANILLA | ICE_CONTROLLED),
&a_engine->ice_in
#endif
@ -4373,6 +4557,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
}
}
if (jb_msec < 0 && jb_msec > -10) {
jb_msec = (a_engine->read_codec.implementation->microseconds_per_packet / 1000) * abs(jb_msec);
}
if (jb_msec < 20 || jb_msec > 10000) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,
"Invalid Jitterbuffer spec [%d] must be between 20 and 10000\n", jb_msec);
@ -4535,7 +4723,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
v_engine->codec_params.remote_sdp_port, v_engine->codec_params.agreed_pt,
a_engine->read_impl.microseconds_per_packet / 1000);
start_video_thread(session);
switch_rtp_set_default_payload(v_engine->rtp_session, v_engine->codec_params.agreed_pt);
}
}
@ -4549,7 +4737,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
const char *rport = NULL;
switch_port_t remote_rtcp_port = v_engine->remote_rtcp_port;
switch_channel_clear_flag(session->channel, CF_REINVITE);
//switch_channel_clear_flag(session->channel, CF_REINVITE);
if (!remote_rtcp_port) {
if ((rport = switch_channel_get_variable(session->channel, "rtp_remote_video_rtcp_port"))) {
@ -4568,6 +4756,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
!((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
/* Reactivate the NAT buster flag. */
switch_rtp_set_flag(v_engine->rtp_session, SWITCH_RTP_FLAG_AUTOADJ);
start_video_thread(session);
}
}
@ -4655,18 +4844,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
if (switch_rtp_ready(v_engine->rtp_session)) {
switch_threadattr_t *thd_attr = NULL;
switch_memory_pool_t *pool = switch_core_session_get_pool(session);
switch_rtp_set_default_payload(v_engine->rtp_session, v_engine->codec_params.agreed_pt);
v_engine->mh.session = session;
switch_threadattr_create(&thd_attr, pool);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
switch_thread_cond_create(&v_engine->mh.cond, pool);
switch_mutex_init(&v_engine->mh.cond_mutex, SWITCH_MUTEX_NESTED, pool);
switch_mutex_init(&v_engine->read_mutex, SWITCH_MUTEX_NESTED, pool);
switch_thread_create(&v_engine->media_thread, thd_attr, video_helper_thread, &v_engine->mh, switch_core_session_get_pool(session));
start_video_thread(session);
}
if (switch_rtp_ready(v_engine->rtp_session)) {
@ -4700,7 +4878,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
ICE_GOOGLE_JINGLE,
NULL
#else
switch_channel_direction(session->channel) ==
switch_ice_direction(session) ==
SWITCH_CALL_DIRECTION_OUTBOUND ? ICE_VANILLA : (ICE_VANILLA | ICE_CONTROLLED),
&v_engine->ice_in
#endif
@ -4750,7 +4928,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
ICE_GOOGLE_JINGLE,
NULL
#else
switch_channel_direction(session->channel) ==
switch_ice_direction(session) ==
SWITCH_CALL_DIRECTION_OUTBOUND ? ICE_VANILLA : (ICE_VANILLA | ICE_CONTROLLED),
&v_engine->ice_in
@ -4819,6 +4997,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
video_up:
if (session && v_engine) {
check_dtls_reinvite(session, v_engine);
}
status = SWITCH_STATUS_SUCCESS;
end:
@ -5275,7 +5457,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
switch_channel_clear_flag(smh->session->channel, CF_DTLS);
}
if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND || switch_channel_test_flag(session->channel, CF_RECOVERING)) {
if (!switch_channel_test_flag(session->channel, CF_WEBRTC) &&
switch_true(switch_channel_get_variable(session->channel, "media_webrtc"))) {
switch_channel_set_flag(session->channel, CF_WEBRTC);
@ -5460,6 +5642,10 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
rate = a_engine->codec_params.rm_rate;
if (!strcasecmp(a_engine->codec_params.rm_encoding, "opus")) {
a_engine->codec_params.adv_channels = 2;
}
if (a_engine->codec_params.adv_channels > 1) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\n",
a_engine->codec_params.agreed_pt, a_engine->codec_params.rm_encoding, rate, a_engine->codec_params.adv_channels);
@ -5577,7 +5763,8 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
}
if (a_engine->rtcp_mux < 1 || switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
if (a_engine->rtcp_mux < 1 || switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND ||
switch_channel_test_flag(session->channel, CF_RECOVERING)) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\n",
tmp1, ice_out->cands[0][0].transport, c2,
@ -5765,7 +5952,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
if (v_engine->codec_params.rm_encoding) {
const char *of;
if (!strcasecmp(v_engine->codec_params.rm_encoding, "VP8")) {
vp8 = v_engine->codec_params.pt;
}
@ -5866,7 +6053,8 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
}
if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND && switch_channel_test_flag(smh->session->channel, CF_DTLS)) {
if ((switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND || switch_channel_test_flag(session->channel, CF_RECOVERING))
&& switch_channel_test_flag(smh->session->channel, CF_DTLS)) {
generate_local_fingerprint(smh, SWITCH_MEDIA_TYPE_VIDEO);
}
@ -5949,7 +6137,8 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
}
if (v_engine->rtcp_mux < 1 || switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
if (v_engine->rtcp_mux < 1 || switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND ||
switch_channel_test_flag(session->channel, CF_RECOVERING)) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\n",
tmp1, ice_out->cands[0][0].transport, c2,
@ -7607,8 +7796,6 @@ SWITCH_DECLARE (void) switch_core_media_recover_session(switch_core_session_t *s
ip = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE);
port = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE);
switch_channel_set_flag(session->channel, CF_RECOVERING);
if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) || !(ip && port)) {
return;
} else {
@ -7728,7 +7915,7 @@ SWITCH_DECLARE (void) switch_core_media_recover_session(switch_core_session_t *s
switch_core_session_get_recovery_crypto_key(session, SWITCH_MEDIA_TYPE_VIDEO);
if ((tmp = switch_channel_get_variable(session->channel, "rtp_last_audio_local_crypto_key"))) {
if ((tmp = switch_channel_get_variable(session->channel, "rtp_last_audio_local_crypto_key")) && a_engine->ssec.remote_crypto_key) {
int idx = atoi(tmp);
a_engine->ssec.local_crypto_key = switch_core_session_strdup(session, tmp);

View File

@ -445,17 +445,26 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_event_send(const char *uuid_
}
SWITCH_DECLARE(void *) switch_core_session_get_private(switch_core_session_t *session)
SWITCH_DECLARE(void *) switch_core_session_get_private_class(switch_core_session_t *session, switch_pvt_class_t index)
{
if (index >= SWITCH_CORE_SESSION_MAX_PRIVATES) {
return NULL;
}
switch_assert(session != NULL);
return session->private_info;
return session->private_info[index];
}
SWITCH_DECLARE(switch_status_t) switch_core_session_set_private(switch_core_session_t *session, void *private_info)
SWITCH_DECLARE(switch_status_t) switch_core_session_set_private_class(switch_core_session_t *session, void *private_info, switch_pvt_class_t index)
{
switch_assert(session != NULL);
session->private_info = private_info;
if (index >= SWITCH_CORE_SESSION_MAX_PRIVATES) {
return SWITCH_STATUS_FALSE;
}
session->private_info[index] = private_info;
return SWITCH_STATUS_SUCCESS;
}

View File

@ -2717,14 +2717,35 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName
if (ep->recover_callback) {
switch_caller_extension_t *extension = NULL;
switch_channel_t *channel = switch_core_session_get_channel(session);
int r = 0;
if ((r = ep->recover_callback(session)) > 0) {
const char *cbname;
if (ep->recover_callback(session) > 0) {
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_channel_set_flag(session->channel, CF_RECOVERING);
if (switch_channel_get_partner_uuid(channel)) {
switch_channel_set_flag(channel, CF_RECOVERING_BRIDGE);
} else {
}
switch_core_media_recover_session(session);
if ((cbname = switch_channel_get_variable(channel, "secondary_recovery_module"))) {
switch_core_recover_callback_t recover_callback;
if ((recover_callback = switch_core_get_secondary_recover_callback(cbname))) {
r = recover_callback(session);
}
}
}
if (r > 0) {
if (!switch_channel_test_flag(channel, CF_RECOVERING_BRIDGE)) {
switch_xml_t callflow, param, x_extension;
if ((extension = switch_caller_extension_new(session, "recovery", "recovery")) == 0) {
abort();

View File

@ -38,6 +38,16 @@
static void switch_core_standard_on_init(switch_core_session_t *session)
{
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard INIT\n", switch_channel_get_name(session->channel));
if (switch_channel_test_flag(session->channel, CF_RECOVERING_BRIDGE)) {
switch_channel_set_state(session->channel, CS_RESET);
} else {
if (switch_channel_test_flag(session->channel, CF_RECOVERING)) {
switch_channel_set_state(session->channel, CS_EXECUTE);
} else {
switch_channel_set_state(session->channel, CS_ROUTING);
}
}
}
static void switch_core_standard_on_hangup(switch_core_session_t *session)
@ -104,6 +114,43 @@ static void switch_core_standard_on_reset(switch_core_session_t *session)
switch_channel_set_variable(session->channel, "call_uuid", switch_core_session_get_uuid(session));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard RESET\n", switch_channel_get_name(session->channel));
if (switch_channel_test_flag(session->channel, CF_RECOVERING_BRIDGE)) {
switch_core_session_t *other_session = NULL;
const char *uuid = switch_core_session_get_uuid(session);
if (switch_channel_test_flag(session->channel, CF_BRIDGE_ORIGINATOR)) {
const char *other_uuid = switch_channel_get_partner_uuid(session->channel);
int x = 0;
if (other_uuid) {
for (x = 0; other_session == NULL && x < 20; x++) {
if (!switch_channel_up(session->channel)) {
break;
}
other_session = switch_core_session_locate(other_uuid);
switch_yield(100000);
}
}
if (other_session) {
switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
switch_channel_clear_flag(session->channel, CF_BRIDGE_ORIGINATOR);
switch_channel_wait_for_state_timeout(other_channel, CS_RESET, 5000);
switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 2000, NULL);
if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) && switch_channel_test_flag(other_channel, CF_PROXY_MODE)) {
switch_ivr_signal_bridge(session, other_session);
} else {
switch_ivr_uuid_bridge(uuid, other_uuid);
}
switch_core_session_rwunlock(other_session);
}
}
switch_channel_clear_flag(session->channel, CF_RECOVERING_BRIDGE);
}
}
static void switch_core_standard_on_routing(switch_core_session_t *session)
@ -208,6 +255,8 @@ static void switch_core_standard_on_execute(switch_core_session_t *session)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard EXECUTE\n", switch_channel_get_name(session->channel));
switch_channel_clear_flag(session->channel, CF_RECOVERING);
switch_channel_set_variable(session->channel, "call_uuid", switch_core_session_get_uuid(session));
if (switch_channel_get_variable(session->channel, "recovered") && !switch_channel_test_flag(session->channel, CF_RECOVERED)) {

View File

@ -67,6 +67,15 @@ struct switch_event_subclass {
int bind;
};
static struct {
switch_event_channel_id_t ID;
switch_thread_rwlock_t *rwlock;
switch_hash_t *hash;
switch_hash_t *lahash;
switch_mutex_t *lamutex;
} event_channel_manager;
#define MAX_DISPATCH_VAL 64
static unsigned int MAX_DISPATCH = MAX_DISPATCH_VAL;
static unsigned int SOFT_MAX_DISPATCH = 0;
@ -81,10 +90,12 @@ static switch_memory_pool_t *THRUNTIME_POOL = NULL;
static switch_thread_t *EVENT_DISPATCH_QUEUE_THREADS[MAX_DISPATCH_VAL] = { 0 };
static uint8_t EVENT_DISPATCH_QUEUE_RUNNING[MAX_DISPATCH_VAL] = { 0 };
static switch_queue_t *EVENT_DISPATCH_QUEUE = NULL;
static switch_queue_t *EVENT_CHANNEL_DISPATCH_QUEUE = NULL;
static switch_mutex_t *EVENT_QUEUE_MUTEX = NULL;
static switch_hash_t *CUSTOM_HASH = NULL;
static int THREAD_COUNT = 0;
static int DISPATCH_THREAD_COUNT = 0;
static int EVENT_CHANNEL_DISPATCH_THREAD_COUNT = 0;
static int SYSTEM_RUNNING = 0;
static uint64_t EVENT_SEQUENCE_NR = 0;
#ifdef SWITCH_EVENT_RECYCLE
@ -92,6 +103,8 @@ static switch_queue_t *EVENT_RECYCLE_QUEUE = NULL;
static switch_queue_t *EVENT_HEADER_RECYCLE_QUEUE = NULL;
#endif
static void unsub_all_switch_event_channel(void);
static char *my_dup(const char *s)
{
size_t len = strlen(s) + 1;
@ -518,6 +531,13 @@ SWITCH_DECLARE(switch_status_t) switch_event_shutdown(void)
SYSTEM_RUNNING = 0;
switch_mutex_unlock(EVENT_QUEUE_MUTEX);
unsub_all_switch_event_channel();
if (EVENT_CHANNEL_DISPATCH_QUEUE) {
switch_queue_trypush(EVENT_CHANNEL_DISPATCH_QUEUE, NULL);
switch_queue_interrupt_all(EVENT_CHANNEL_DISPATCH_QUEUE);
}
if (runtime.events_use_dispatch) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Stopping dispatch queues\n");
@ -565,6 +585,8 @@ SWITCH_DECLARE(switch_status_t) switch_event_shutdown(void)
}
}
switch_core_hash_destroy(&event_channel_manager.lahash);
switch_core_hash_destroy(&CUSTOM_HASH);
switch_core_memory_reclaim_events();
@ -633,14 +655,6 @@ SWITCH_DECLARE(void) switch_event_launch_dispatch_threads(uint32_t max)
SWITCH_DECLARE(switch_status_t) switch_event_init(switch_memory_pool_t *pool)
{
//switch_threadattr_t *thd_attr;
/*
This statement doesn't do anything commenting it out for now.
switch_assert(switch_arraylen(EVENT_NAMES) == SWITCH_EVENT_ALL + 1);
*/
/* don't need any more dispatch threads than we have CPU's*/
MAX_DISPATCH = (switch_core_cpu_count() / 2) + 1;
if (MAX_DISPATCH < 2) {
@ -656,6 +670,13 @@ SWITCH_DECLARE(switch_status_t) switch_event_init(switch_memory_pool_t *pool)
switch_mutex_init(&EVENT_QUEUE_MUTEX, SWITCH_MUTEX_NESTED, RUNTIME_POOL);
switch_core_hash_init(&CUSTOM_HASH, RUNTIME_POOL);
switch_core_hash_init(&event_channel_manager.lahash, RUNTIME_POOL);
switch_mutex_init(&event_channel_manager.lamutex, SWITCH_MUTEX_NESTED, RUNTIME_POOL);
switch_thread_rwlock_create(&event_channel_manager.rwlock, RUNTIME_POOL);
switch_core_hash_init(&event_channel_manager.hash, RUNTIME_POOL);
event_channel_manager.ID = 1;
switch_mutex_lock(EVENT_QUEUE_MUTEX);
SYSTEM_RUNNING = -1;
switch_mutex_unlock(EVENT_QUEUE_MUTEX);
@ -1733,13 +1754,11 @@ SWITCH_DECLARE(switch_status_t) switch_event_create_json(switch_event_t **event,
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_event_serialize_json(switch_event_t *event, char **str)
SWITCH_DECLARE(switch_status_t) switch_event_serialize_json_obj(switch_event_t *event, cJSON **json)
{
switch_event_header_t *hp;
cJSON *cj;
*str = NULL;
cj = cJSON_CreateObject();
for (hp = event->headers; hp; hp = hp->next) {
@ -1768,12 +1787,27 @@ SWITCH_DECLARE(switch_status_t) switch_event_serialize_json(switch_event_t *even
cJSON_AddItemToObject(cj, "_body", cJSON_CreateString(event->body));
}
*str = cJSON_Print(cj);
cJSON_Delete(cj);
*json = cj;
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_event_serialize_json(switch_event_t *event, char **str)
{
cJSON *cj;
*str = NULL;
if (switch_event_serialize_json_obj(event, &cj) == SWITCH_STATUS_SUCCESS) {
*str = cJSON_PrintUnformatted(cj);
cJSON_Delete(cj);
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
static switch_xml_t add_xml_header(switch_xml_t xml, char *name, char *value, int offset)
{
switch_xml_t header = switch_xml_add_child_d(xml, name, offset);
@ -2528,6 +2562,36 @@ SWITCH_DECLARE(int) switch_event_check_permission_list(switch_event_t *list, con
return r;
}
SWITCH_DECLARE(void) switch_json_add_presence_data_cols(switch_event_t *event, cJSON *json, const char *prefix)
{
const char *data;
if (!prefix) prefix = "";
if ((data = switch_event_get_header(event, "presence_data_cols"))) {
char *cols[128] = { 0 };
char header_name[128] = "";
int col_count = 0, i = 0;
char *data_copy = NULL;
data_copy = strdup(data);
col_count = switch_split(data_copy, ':', cols);
for (i = 0; i < col_count; i++) {
const char *val = NULL;
switch_snprintf(header_name, sizeof(header_name), "%s%s", prefix, cols[i]);
val = switch_event_get_header(event, cols[i]);
json_add_child_string(json, header_name, val);
}
switch_safe_free(data_copy);
}
}
SWITCH_DECLARE(void) switch_event_add_presence_data_cols(switch_channel_t *channel, switch_event_t *event, const char *prefix)
{
const char *data;
@ -2557,6 +2621,792 @@ SWITCH_DECLARE(void) switch_event_add_presence_data_cols(switch_channel_t *chann
}
struct switch_event_channel_sub_node_head_s;
typedef struct switch_event_channel_sub_node_s {
switch_event_channel_func_t func;
switch_event_channel_id_t id;
struct switch_event_channel_sub_node_head_s *head;
struct switch_event_channel_sub_node_s *next;
} switch_event_channel_sub_node_t;
typedef struct switch_event_channel_sub_node_head_s {
switch_event_channel_sub_node_t *node;
switch_event_channel_sub_node_t *tail;
char *event_channel;
} switch_event_channel_sub_node_head_t;
static uint32_t switch_event_channel_unsub_head(switch_event_channel_func_t func, switch_event_channel_sub_node_head_t *head)
{
uint32_t x = 0;
switch_event_channel_sub_node_t *thisnp = NULL, *np, *last = NULL;
np = head->tail = head->node;
while (np) {
thisnp = np;
np = np->next;
if (!func || thisnp->func == func) {
x++;
if (last) {
last->next = np;
} else {
head->node = np;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "UNSUBBING %p [%s]\n", (void *)(intptr_t)thisnp->func, thisnp->head->event_channel);
thisnp->func = NULL;
free(thisnp);
} else {
last = thisnp;
head->tail = last;
}
}
return x;
}
static void unsub_all_switch_event_channel(void)
{
switch_hash_index_t *hi;
void *val;
switch_event_channel_sub_node_head_t *head;
switch_thread_rwlock_wrlock(event_channel_manager.rwlock);
top:
head = NULL;
for (hi = switch_hash_first(NULL, event_channel_manager.hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, NULL, NULL, &val);
head = (switch_event_channel_sub_node_head_t *) val;
switch_event_channel_unsub_head(NULL, head);
switch_core_hash_delete(event_channel_manager.hash, head->event_channel);
free(head->event_channel);
free(head);
goto top;
}
switch_thread_rwlock_unlock(event_channel_manager.rwlock);
}
static uint32_t switch_event_channel_unsub_channel(switch_event_channel_func_t func, const char *event_channel)
{
switch_event_channel_sub_node_head_t *head;
uint32_t x = 0;
switch_thread_rwlock_wrlock(event_channel_manager.rwlock);
if (!event_channel) {
switch_hash_index_t *hi;
void *val;
for (hi = switch_hash_first(NULL, event_channel_manager.hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, NULL, NULL, &val);
if (val) {
head = (switch_event_channel_sub_node_head_t *) val;
x += switch_event_channel_unsub_head(func, head);
}
}
} else {
if ((head = switch_core_hash_find(event_channel_manager.hash, event_channel))) {
x += switch_event_channel_unsub_head(func, head);
}
}
switch_thread_rwlock_unlock(event_channel_manager.rwlock);
return x;
}
static switch_status_t switch_event_channel_sub_channel(const char *event_channel, switch_event_channel_func_t func, switch_event_channel_id_t id)
{
switch_event_channel_sub_node_t *node, *np;
switch_event_channel_sub_node_head_t *head;
switch_status_t status = SWITCH_STATUS_FALSE;
switch_thread_rwlock_wrlock(event_channel_manager.rwlock);
if (!(head = switch_core_hash_find(event_channel_manager.hash, event_channel))) {
switch_zmalloc(head, sizeof(*head));
head->event_channel = strdup(event_channel);
switch_core_hash_insert(event_channel_manager.hash, event_channel, head);
switch_zmalloc(node, sizeof(*node));
node->func = func;
node->id = id;
node->head = head;
head->node = node;
head->tail = node;
status = SWITCH_STATUS_SUCCESS;
} else {
int exist = 0;
for (np = head->node; np; np = np->next) {
if (np->func == func) {
exist = 1;
break;
}
}
if (!exist) {
switch_zmalloc(node, sizeof(*node));
node->func = func;
node->id = id;
node->head = head;
if (!head->node) {
head->node = node;
head->tail = node;
} else {
head->tail->next = node;
head->tail = head->tail->next;
}
status = SWITCH_STATUS_SUCCESS;
}
}
switch_thread_rwlock_unlock(event_channel_manager.rwlock);
return status;
}
typedef struct {
char *event_channel;
cJSON *json;
char *key;
switch_event_channel_id_t id;
} event_channel_data_t;
static uint32_t _switch_event_channel_broadcast(const char *event_channel, const char *broadcast_channel,
cJSON *json, const char *key, switch_event_channel_id_t id)
{
switch_event_channel_sub_node_t *np;
switch_event_channel_sub_node_head_t *head;
uint32_t x = 0;
switch_thread_rwlock_rdlock(event_channel_manager.rwlock);
if ((head = switch_core_hash_find(event_channel_manager.hash, event_channel))) {
for (np = head->node; np; np = np->next) {
if (np->id == id) {
continue;
}
np->func(broadcast_channel, json, key, id);
x++;
}
}
switch_thread_rwlock_unlock(event_channel_manager.rwlock);
return x;
}
static void destroy_ecd(event_channel_data_t **ecdP)
{
event_channel_data_t *ecd = *ecdP;
*ecdP = NULL;
switch_safe_free(ecd->event_channel);
switch_safe_free(ecd->key);
if (ecd->json) {
cJSON_Delete(ecd->json);
ecd->json = NULL;
}
free(ecd);
}
static void ecd_deliver(event_channel_data_t **ecdP)
{
event_channel_data_t *ecd = *ecdP;
char *p;
*ecdP = NULL;
_switch_event_channel_broadcast(ecd->event_channel, ecd->event_channel, ecd->json, ecd->key, ecd->id);
if ((p = strchr(ecd->event_channel, '.'))) {
char *main_channel = strdup(ecd->event_channel);
p = strchr(main_channel, '.');
*p = '\0';
_switch_event_channel_broadcast(main_channel, ecd->event_channel, ecd->json, ecd->key, ecd->id);
free(main_channel);
}
_switch_event_channel_broadcast(SWITCH_EVENT_CHANNEL_GLOBAL, ecd->event_channel, ecd->json, ecd->key, ecd->id);
destroy_ecd(&ecd);
}
static void *SWITCH_THREAD_FUNC switch_event_channel_deliver_thread(switch_thread_t *thread, void *obj)
{
switch_queue_t *queue = (switch_queue_t *) obj;
void *pop = NULL;
event_channel_data_t *ecd = NULL;
switch_mutex_lock(EVENT_QUEUE_MUTEX);
THREAD_COUNT++;
EVENT_CHANNEL_DISPATCH_THREAD_COUNT++;
switch_mutex_unlock(EVENT_QUEUE_MUTEX);
while(SYSTEM_RUNNING) {
if (switch_queue_pop(queue, &pop) != SWITCH_STATUS_SUCCESS) {
continue;
}
if (!pop) {
break;
}
ecd = (event_channel_data_t *) pop;
ecd_deliver(&ecd);
switch_os_yield();
}
while (switch_queue_trypop(queue, &pop) == SWITCH_STATUS_SUCCESS) {
ecd = (event_channel_data_t *) pop;
destroy_ecd(&ecd);
}
switch_mutex_lock(EVENT_QUEUE_MUTEX);
THREAD_COUNT--;
EVENT_CHANNEL_DISPATCH_THREAD_COUNT--;
switch_mutex_unlock(EVENT_QUEUE_MUTEX);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Event Channel Dispatch Thread Ended.\n");
return NULL;
}
SWITCH_DECLARE(switch_status_t) switch_event_channel_broadcast(const char *event_channel, cJSON **json, const char *key, switch_event_channel_id_t id)
{
event_channel_data_t *ecd = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS;
if (!SYSTEM_RUNNING) {
cJSON_Delete(*json);
*json = NULL;
return SWITCH_STATUS_FALSE;
}
switch_zmalloc(ecd, sizeof(*ecd));
ecd->event_channel = strdup(event_channel);
ecd->json = *json;
ecd->key = strdup(key);
ecd->id = id;
*json = NULL;
if (!EVENT_CHANNEL_DISPATCH_THREAD_COUNT && SYSTEM_RUNNING) {
switch_thread_data_t *td;
if (!EVENT_CHANNEL_DISPATCH_QUEUE) {
switch_queue_create(&EVENT_CHANNEL_DISPATCH_QUEUE, DISPATCH_QUEUE_LEN * MAX_DISPATCH, THRUNTIME_POOL);
}
td = malloc(sizeof(*td));
switch_assert(td);
td->alloc = 1;
td->func = switch_event_channel_deliver_thread;
td->obj = EVENT_CHANNEL_DISPATCH_QUEUE;
td->pool = NULL;
switch_thread_pool_launch_thread(&td);
}
if ((status = switch_queue_trypush(EVENT_CHANNEL_DISPATCH_QUEUE, ecd) != SWITCH_STATUS_SUCCESS)) {
cJSON_Delete(ecd->json);
ecd->json = NULL;
destroy_ecd(&ecd);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Event Channel Queue failure for channel %s\n", event_channel);
} else {
ecd = NULL;
}
return status;
}
SWITCH_DECLARE(uint32_t) switch_event_channel_unbind(const char *event_channel, switch_event_channel_func_t func)
{
return switch_event_channel_unsub_channel(func, event_channel);
}
SWITCH_DECLARE(switch_status_t) switch_event_channel_bind(const char *event_channel, switch_event_channel_func_t func, switch_event_channel_id_t *id)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_assert(id);
if (!*id) {
switch_thread_rwlock_wrlock(event_channel_manager.rwlock);
*id = event_channel_manager.ID++;
switch_thread_rwlock_unlock(event_channel_manager.rwlock);
}
status = switch_event_channel_sub_channel(event_channel, func, *id);
return status;
}
typedef struct la_node_s {
char *name;
cJSON *obj;
struct la_node_s *next;
int pos;
} la_node_t;
struct switch_live_array_s {
char *event_channel;
char *name;
char *key;
la_node_t *head;
la_node_t *tail;
switch_memory_pool_t *pool;
switch_hash_t *hash;
switch_mutex_t *mutex;
uint32_t serno;
int pos;
switch_bool_t visible;
switch_bool_t new;
switch_event_channel_id_t channel_id;
switch_live_array_command_handler_t command_handler;
void *user_data;
};
SWITCH_DECLARE(switch_status_t) switch_live_array_visible(switch_live_array_t *la, switch_bool_t visible, switch_bool_t force)
{
switch_status_t status = SWITCH_STATUS_FALSE;
switch_mutex_lock(la->mutex);
if (la->visible != visible || force) {
cJSON *msg, *data;
msg = cJSON_CreateObject();
data = json_add_child_obj(msg, "data", NULL);
cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(la->event_channel));
cJSON_AddItemToObject(data, "action", cJSON_CreateString(visible ? "hide" : "show"));
cJSON_AddItemToObject(data, "wireSerno", cJSON_CreateNumber(la->serno++));
switch_event_channel_broadcast(la->event_channel, &msg, __FILE__, la->channel_id);
la->visible = visible;
}
switch_mutex_unlock(la->mutex);
return status;
}
SWITCH_DECLARE(switch_status_t) switch_live_array_clear(switch_live_array_t *la)
{
la_node_t *cur, *np;
cJSON *msg, *data;
switch_mutex_lock(la->mutex);
np = la->head;
msg = cJSON_CreateObject();
data = json_add_child_obj(msg, "data", NULL);
cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(la->event_channel));
cJSON_AddItemToObject(data, "action", cJSON_CreateString("clear"));
cJSON_AddItemToObject(data, "name", cJSON_CreateString(la->name));
cJSON_AddItemToObject(data, "wireSerno", cJSON_CreateNumber(-1));
cJSON_AddItemToObject(data, "data", cJSON_CreateObject());
switch_event_channel_broadcast(la->event_channel, &msg, __FILE__, la->channel_id);
while(np) {
cur = np;
cJSON_Delete(cur->obj);
free(cur->name);
free(cur);
np = np->next;
}
la->head = la->tail = NULL;
switch_mutex_unlock(la->mutex);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_live_array_bootstrap(switch_live_array_t *la, const char *sessid, switch_event_channel_id_t channel_id)
{
la_node_t *np;
cJSON *msg, *data;
switch_mutex_lock(la->mutex);
#if OLD_WAY
msg = cJSON_CreateObject();
data = json_add_child_obj(msg, "data", NULL);
cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(la->event_channel));
cJSON_AddItemToObject(data, "action", cJSON_CreateString("clear"));
cJSON_AddItemToObject(data, "name", cJSON_CreateString(la->name));
cJSON_AddItemToObject(data, "wireSerno", cJSON_CreateNumber(-1));
cJSON_AddItemToObject(data, "data", cJSON_CreateObject());
switch_event_channel_broadcast(la->event_channel, &msg, __FILE__, channel_id);
for (np = la->head; np; np = np->next) {
msg = cJSON_CreateObject();
data = json_add_child_obj(msg, "data", NULL);
cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(la->event_channel));
cJSON_AddItemToObject(data, "action", cJSON_CreateString("add"));
cJSON_AddItemToObject(data, "name", cJSON_CreateString(la->name));
cJSON_AddItemToObject(data, "hashKey", cJSON_CreateString(np->name));
cJSON_AddItemToObject(data, "wireSerno", cJSON_CreateNumber(la->serno++));
cJSON_AddItemToObject(data, "data", cJSON_Duplicate(np->obj, 1));
if (sessid) {
cJSON_AddItemToObject(msg, "sessid", cJSON_CreateString(sessid));
}
switch_event_channel_broadcast(la->event_channel, &msg, __FILE__, channel_id);
}
#else
msg = cJSON_CreateObject();
data = json_add_child_obj(msg, "data", NULL);
cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(la->event_channel));
cJSON_AddItemToObject(data, "action", cJSON_CreateString("bootObj"));
cJSON_AddItemToObject(data, "name", cJSON_CreateString(la->name));
cJSON_AddItemToObject(data, "wireSerno", cJSON_CreateNumber(la->serno++));
if (sessid) {
cJSON_AddItemToObject(msg, "sessid", cJSON_CreateString(sessid));
}
data = json_add_child_array(data, "data");
for (np = la->head; np; np = np->next) {
cJSON *row = cJSON_CreateArray();
cJSON_AddItemToArray(row, cJSON_CreateString(np->name));
cJSON_AddItemToArray(row, cJSON_Duplicate(np->obj, 1));
cJSON_AddItemToArray(data, row);
}
switch_event_channel_broadcast(la->event_channel, &msg, __FILE__, channel_id);
#endif
if (!la->visible) {
switch_live_array_visible(la, SWITCH_FALSE, SWITCH_TRUE);
}
switch_mutex_unlock(la->mutex);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_live_array_destroy(switch_live_array_t **live_arrayP)
{
switch_live_array_t *la = *live_arrayP;
switch_memory_pool_t *pool;
*live_arrayP = NULL;
pool = la->pool;
switch_live_array_clear(la);
switch_core_hash_destroy(&la->hash);
switch_mutex_lock(event_channel_manager.lamutex);
switch_core_hash_delete(event_channel_manager.lahash, la->key);
switch_mutex_unlock(event_channel_manager.lamutex);
switch_core_destroy_memory_pool(&pool);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_bool_t) switch_live_array_isnew(switch_live_array_t *la)
{
return la->new;
}
SWITCH_DECLARE(switch_status_t) switch_live_array_create(const char *event_channel, const char *name,
switch_event_channel_id_t channel_id, switch_live_array_t **live_arrayP)
{
switch_live_array_t *la = NULL;
switch_memory_pool_t *pool;
char *key = NULL;
switch_core_new_memory_pool(&pool);
key = switch_core_sprintf(pool, "%s.%s", event_channel, name);
switch_mutex_lock(event_channel_manager.lamutex);
la = switch_core_hash_find(event_channel_manager.lahash, key);
switch_mutex_unlock(event_channel_manager.lamutex);
if (la) {
la->new = SWITCH_FALSE;
} else {
la = switch_core_alloc(pool, sizeof(*la));
la->pool = pool;
la->serno = 1;
la->visible = SWITCH_TRUE;
la->event_channel = switch_core_strdup(la->pool, event_channel);
la->name = switch_core_strdup(la->pool, name);
la->key = key;
la->new = SWITCH_TRUE;
la->channel_id = channel_id;
switch_core_hash_init(&la->hash, la->pool);
switch_mutex_init(&la->mutex, SWITCH_MUTEX_NESTED, la->pool);
switch_mutex_lock(event_channel_manager.lamutex);
switch_core_hash_insert(event_channel_manager.lahash, la->key, la);
switch_mutex_unlock(event_channel_manager.lamutex);
}
*live_arrayP = la;
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(cJSON *) switch_live_array_get(switch_live_array_t *la, const char *name)
{
la_node_t *node;
cJSON *dup = NULL;
switch_mutex_lock(la->mutex);
if ((node = switch_core_hash_find(la->hash, name))) {
dup = cJSON_Duplicate(node->obj, 1);
}
switch_mutex_unlock(la->mutex);
return dup;
}
SWITCH_DECLARE(cJSON *) switch_live_array_get_idx(switch_live_array_t *la, int idx)
{
la_node_t *node;
cJSON *dup = NULL;
switch_mutex_lock(la->mutex);
for (node = la->head; node; node = node->next) {
if (node->pos == idx) {
dup = cJSON_Duplicate(node->obj, 1);
break;
}
}
switch_mutex_unlock(la->mutex);
return dup;
}
SWITCH_DECLARE(void) switch_live_array_lock(switch_live_array_t *la)
{
switch_mutex_lock(la->mutex);
}
SWITCH_DECLARE(void) switch_live_array_unlock(switch_live_array_t *la)
{
switch_mutex_unlock(la->mutex);
}
SWITCH_DECLARE(switch_status_t) switch_live_array_del(switch_live_array_t *la, const char *name)
{
switch_status_t status = SWITCH_STATUS_FALSE;
la_node_t *node, *cur, *np, *last = NULL;
cJSON *msg, *data = NULL;
switch_mutex_lock(la->mutex);
if ((node = switch_core_hash_find(la->hash, name))) {
np = la->head;
while(np) {
cur = np;
np = np->next;
if (cur == node) {
if (last) {
last->next = cur->next;
} else {
la->head = cur->next;
}
switch_core_hash_delete(la->hash, name);
msg = cJSON_CreateObject();
data = json_add_child_obj(msg, "data", NULL);
cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(la->event_channel));
cJSON_AddItemToObject(data, "name", cJSON_CreateString(la->name));
cJSON_AddItemToObject(data, "action", cJSON_CreateString("del"));
cJSON_AddItemToObject(data, "hashKey", cJSON_CreateString(cur->name));
cJSON_AddItemToObject(data, "wireSerno", cJSON_CreateNumber(la->serno++));
cJSON_AddItemToObject(data, "data", cur->obj);
cur->obj = NULL;
switch_event_channel_broadcast(la->event_channel, &msg, __FILE__, la->channel_id);
free(cur->name);
free(cur);
} else {
cur->pos = la->pos++;
la->tail = cur;
last = cur;
}
}
}
switch_mutex_unlock(la->mutex);
return status;
}
SWITCH_DECLARE(switch_status_t) switch_live_array_add(switch_live_array_t *la, const char *name, int index, cJSON **obj, switch_bool_t duplicate)
{
la_node_t *node;
switch_status_t status = SWITCH_STATUS_SUCCESS;
const char *action = "add";
cJSON *msg = NULL, *data = NULL;
switch_mutex_lock(la->mutex);
if ((node = switch_core_hash_find(la->hash, name))) {
action = "modify";
if (node->obj) {
if (duplicate) {
cJSON_Delete(node->obj);
node->obj = NULL;
}
}
} else {
switch_zmalloc(node, sizeof(*node));
node->name = strdup(name);
switch_core_hash_insert(la->hash, name, node);
if (index > -1 && index < la->pos && la->head) {
la_node_t *np, *last = NULL;
int i = 0;
for(np = la->head; np; np = np->next) {
if (i == index) {
if (last) {
node->next = last->next;
last->next = node;
np = node;
} else {
node->next = la->head;
la->head = node;
np = node;
}
}
np->pos = i;
la->tail = np;
last = np;
i++;
}
} else {
node->pos = la->pos++;
index = node->pos;
if (!la->head) {
la->head = node;
} else {
la->tail->next = node;
}
la->tail = node;
}
}
if (duplicate) {
node->obj = cJSON_Duplicate(*obj, 1);
} else {
node->obj = *obj;
}
msg = cJSON_CreateObject();
data = json_add_child_obj(msg, "data", NULL);
cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(la->event_channel));
cJSON_AddItemToObject(data, "action", cJSON_CreateString(action));
if (index > -1) {
cJSON_AddItemToObject(data, "arrIndex", cJSON_CreateNumber(index));
}
cJSON_AddItemToObject(data, "name", cJSON_CreateString(la->name));
cJSON_AddItemToObject(data, "hashKey", cJSON_CreateString(node->name));
cJSON_AddItemToObject(data, "wireSerno", cJSON_CreateNumber(la->serno++));
cJSON_AddItemToObject(data, "data", cJSON_Duplicate(node->obj, 1));
switch_event_channel_broadcast(la->event_channel, &msg, __FILE__, la->channel_id);
switch_mutex_unlock(la->mutex);
return status;
}
SWITCH_DECLARE(void) switch_live_array_set_user_data(switch_live_array_t *la, void *user_data)
{
switch_assert(la);
la->user_data = user_data;
}
SWITCH_DECLARE(void) switch_live_array_set_command_handler(switch_live_array_t *la, switch_live_array_command_handler_t command_handler)
{
switch_assert(la);
la->command_handler = command_handler;
}
SWITCH_DECLARE(void) switch_live_array_parse_json(cJSON *json, switch_event_channel_id_t channel_id)
{
const char *context = NULL, *name = NULL;
switch_live_array_t *la = NULL;
cJSON *jla = NULL;
if ((jla = cJSON_GetObjectItem(json, "data")) && (jla = cJSON_GetObjectItem(jla, "liveArray"))) {
if ((context = cJSON_GetObjectCstr(jla, "context")) && (name = cJSON_GetObjectCstr(jla, "name"))) {
const char *command = cJSON_GetObjectCstr(jla, "command");
const char *sessid = cJSON_GetObjectCstr(json, "sessid");
if (command) {
switch_live_array_create(context, name, channel_id, &la);
if (!strcasecmp(command, "bootstrap")) {
switch_live_array_bootstrap(la, sessid, channel_id);
} else {
if (la->command_handler) {
la->command_handler(la, command, sessid, jla, la->user_data);
}
}
}
}
}
}
/* For Emacs:
* Local Variables:

View File

@ -487,7 +487,20 @@ static char *print_object(cJSON *item,int depth,int fmt)
/* Get Array size/item / object item. */
SWITCH_DECLARE(int) cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
SWITCH_DECLARE(cJSON *)cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
SWITCH_DECLARE(cJSON *)cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
SWITCH_DECLARE(cJSON *)cJSON_GetObjectItem(const cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
SWITCH_DECLARE(const char *)cJSON_GetObjectCstr(const cJSON *object, const char *string)
{
cJSON *cj = cJSON_GetObjectItem(object, string);
if (!cj || cj->type != cJSON_String || !cj->valuestring) return NULL;
return cj->valuestring;
}
/* Utility for array list handling. */
static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
@ -554,3 +567,27 @@ SWITCH_DECLARE(cJSON *) cJSON_Duplicate(cJSON *item,int recurse)
}
return newitem;
}
SWITCH_DECLARE(cJSON *) cJSON_CreateStringPrintf(const char *fmt, ...)
{
va_list ap;
char *str;
cJSON *item;
va_start(ap, fmt);
str = switch_vmprintf(fmt, ap);
va_end(ap);
if (!str) return NULL;
if ((item = cJSON_New_Item())) {
item->type=cJSON_String;
item->valuestring = str;
} else {
free(str);
}
return item;
}

View File

@ -65,6 +65,7 @@ struct switch_loadable_module_container {
switch_hash_t *application_hash;
switch_hash_t *chat_application_hash;
switch_hash_t *api_hash;
switch_hash_t *json_api_hash;
switch_hash_t *file_hash;
switch_hash_t *speech_hash;
switch_hash_t *asr_hash;
@ -73,6 +74,7 @@ struct switch_loadable_module_container {
switch_hash_t *say_hash;
switch_hash_t *management_hash;
switch_hash_t *limit_hash;
switch_hash_t *secondary_recover_hash;
switch_mutex_t *mutex;
switch_memory_pool_t *pool;
};
@ -318,6 +320,29 @@ static switch_status_t switch_loadable_module_process(char *key, switch_loadable
}
}
if (new_module->module_interface->json_api_interface) {
const switch_json_api_interface_t *ptr;
for (ptr = new_module->module_interface->json_api_interface; ptr; ptr = ptr->next) {
if (!ptr->interface_name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to load JSON api interface from %s due to no interface name.\n", key);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding JSON API Function '%s'\n", ptr->interface_name);
if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "json_api");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "description", switch_str_nil(ptr->desc));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "syntax", switch_str_nil(ptr->syntax));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", new_module->key);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "filename", new_module->filename);
switch_event_fire(&event);
added++;
}
switch_core_hash_insert(loadable_modules.json_api_hash, ptr->interface_name, (const void *) ptr);
}
}
}
if (new_module->module_interface->file_interface) {
const switch_file_interface_t *ptr;
@ -1047,6 +1072,36 @@ static switch_status_t switch_loadable_module_unprocess(switch_loadable_module_t
}
}
if (old_module->module_interface->json_api_interface) {
const switch_json_api_interface_t *ptr;
for (ptr = old_module->module_interface->json_api_interface; ptr; ptr = ptr->next) {
if (ptr->interface_name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Deleting API Function '%s'\n", ptr->interface_name);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock interface '%s' to wait for existing references.\n",
ptr->interface_name);
if (switch_thread_rwlock_trywrlock_timeout(ptr->rwlock, 10) == SWITCH_STATUS_SUCCESS) {
switch_thread_rwlock_unlock(ptr->rwlock);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Giving up on '%s' waiting for existing references.\n", ptr->interface_name);
}
if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "api");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "description", switch_str_nil(ptr->desc));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "syntax", switch_str_nil(ptr->syntax));
switch_event_fire(&event);
removed++;
}
switch_core_hash_delete(loadable_modules.json_api_hash, ptr->interface_name);
}
}
}
if (old_module->module_interface->file_interface) {
const switch_file_interface_t *ptr;
@ -1721,6 +1776,7 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init(switch_bool_t autolo
switch_core_hash_init_nocase(&loadable_modules.application_hash, loadable_modules.pool);
switch_core_hash_init_nocase(&loadable_modules.chat_application_hash, loadable_modules.pool);
switch_core_hash_init_nocase(&loadable_modules.api_hash, loadable_modules.pool);
switch_core_hash_init_nocase(&loadable_modules.json_api_hash, loadable_modules.pool);
switch_core_hash_init(&loadable_modules.file_hash, loadable_modules.pool);
switch_core_hash_init_nocase(&loadable_modules.speech_hash, loadable_modules.pool);
switch_core_hash_init_nocase(&loadable_modules.asr_hash, loadable_modules.pool);
@ -1730,6 +1786,7 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init(switch_bool_t autolo
switch_core_hash_init_nocase(&loadable_modules.management_hash, loadable_modules.pool);
switch_core_hash_init_nocase(&loadable_modules.limit_hash, loadable_modules.pool);
switch_core_hash_init_nocase(&loadable_modules.dialplan_hash, loadable_modules.pool);
switch_core_hash_init(&loadable_modules.secondary_recover_hash, loadable_modules.pool);
switch_mutex_init(&loadable_modules.mutex, SWITCH_MUTEX_NESTED, loadable_modules.pool);
if (!autoload) return SWITCH_STATUS_SUCCESS;
@ -1945,6 +2002,7 @@ SWITCH_DECLARE(void) switch_loadable_module_shutdown(void)
switch_core_hash_destroy(&loadable_modules.application_hash);
switch_core_hash_destroy(&loadable_modules.chat_application_hash);
switch_core_hash_destroy(&loadable_modules.api_hash);
switch_core_hash_destroy(&loadable_modules.json_api_hash);
switch_core_hash_destroy(&loadable_modules.file_hash);
switch_core_hash_destroy(&loadable_modules.speech_hash);
switch_core_hash_destroy(&loadable_modules.asr_hash);
@ -2014,6 +2072,7 @@ HASH_FUNC(timer)
HASH_FUNC(application)
HASH_FUNC(chat_application)
HASH_FUNC(api)
HASH_FUNC(json_api)
HASH_FUNC(file)
HASH_FUNC(speech)
HASH_FUNC(asr)
@ -2369,6 +2428,46 @@ SWITCH_DECLARE(switch_status_t) switch_api_execute(const char *cmd, const char *
return status;
}
SWITCH_DECLARE(switch_status_t) switch_json_api_execute(cJSON *json, switch_core_session_t *session, cJSON **retval)
{
switch_json_api_interface_t *json_api;
switch_status_t status;
cJSON *function, *json_reply = NULL;
switch_assert(json);
function = cJSON_GetObjectItem(json, "command");
if (function && function->valuestring
&& cJSON_GetObjectItem(json, "data") && (json_api = switch_loadable_module_get_json_api_interface(function->valuestring)) != 0) {
if ((status = json_api->function(json, session, &json_reply)) != SWITCH_STATUS_SUCCESS) {
cJSON_AddItemToObject(json, "status", cJSON_CreateString("error"));
cJSON_AddItemToObject(json, "message", cJSON_CreateString("The command returned an error"));
} else {
cJSON_AddItemToObject(json, "status", cJSON_CreateString("success"));
}
if (!json_reply) {
json_reply = cJSON_CreateNull();
}
if (retval) {
*retval = json_reply;
} else {
cJSON_AddItemToObject(json, "response", json_reply);
}
UNPROTECT_INTERFACE(json_api);
} else {
status = SWITCH_STATUS_FALSE;
cJSON_AddItemToObject(json, "status", cJSON_CreateString("error"));
cJSON_AddItemToObject(json, "message", cJSON_CreateString("Invalid request or non-existant command"));
cJSON_AddItemToObject(json, "response", cJSON_CreateNull());
}
return status;
}
SWITCH_DECLARE(switch_loadable_module_interface_t *) switch_loadable_module_create_module_interface(switch_memory_pool_t *pool, const char *name)
{
@ -2425,6 +2524,9 @@ SWITCH_DECLARE(void *) switch_loadable_module_create_interface(switch_loadable_m
case SWITCH_API_INTERFACE:
ALLOC_INTERFACE(api)
case SWITCH_JSON_API_INTERFACE:
ALLOC_INTERFACE(json_api)
case SWITCH_FILE_INTERFACE:
ALLOC_INTERFACE(file)
@ -2549,7 +2651,42 @@ SWITCH_DECLARE(void) switch_say_file(switch_say_file_handle_t *sh, const char *f
va_end(ap);
}
SWITCH_DECLARE(switch_core_recover_callback_t) switch_core_get_secondary_recover_callback(const char *key)
{
switch_core_recover_callback_t cb;
switch_mutex_lock(loadable_modules.mutex);
cb = (switch_core_recover_callback_t) (intptr_t) switch_core_hash_find(loadable_modules.secondary_recover_hash, key);
switch_mutex_unlock(loadable_modules.mutex);
return cb;
}
SWITCH_DECLARE(switch_status_t) switch_core_register_secondary_recover_callback(const char *key, switch_core_recover_callback_t cb)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_assert(cb);
switch_mutex_lock(loadable_modules.mutex);
if (switch_core_hash_find(loadable_modules.secondary_recover_hash, key)) {
status = SWITCH_STATUS_FALSE;
} else {
switch_core_hash_insert(loadable_modules.secondary_recover_hash, key, (void *)(intptr_t) cb);
}
switch_mutex_unlock(loadable_modules.mutex);
return status;
}
SWITCH_DECLARE(void) switch_core_unregister_secondary_recover_callback(const char *key)
{
switch_mutex_lock(loadable_modules.mutex);
switch_core_hash_delete(loadable_modules.secondary_recover_hash, key);
switch_mutex_unlock(loadable_modules.mutex);
}
/* For Emacs:

View File

@ -61,7 +61,7 @@
#define WRITE_INC(rtp_session) switch_mutex_lock(rtp_session->write_mutex); rtp_session->writing++
#define WRITE_DEC(rtp_session) switch_mutex_unlock(rtp_session->write_mutex); rtp_session->writing--
#define RTP_STUN_FREQ 2000000
#define RTP_STUN_FREQ 1000000
#define rtp_header_len 12
#define RTP_START_PORT 16384
#define RTP_END_PORT 32768
@ -713,7 +713,7 @@ static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice)
elapsed = (unsigned int) ((switch_micro_time_now() - rtp_session->last_stun) / 1000);
if (elapsed > 30000) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "No stun for a long time!\n");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "No %s stun for a long time!\n", rtp_type(rtp_session));
rtp_session->last_stun = switch_micro_time_now();
//status = SWITCH_STATUS_GENERR;
//goto end;
@ -912,7 +912,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
char *host = NULL;
ice->missed_count++;
//switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_CRIT, "missed %d\n", ice->missed_count);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING, "missed %d\n", ice->missed_count);
if (elapsed > 20000 && pri) {
int i, j;
@ -991,6 +991,8 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
}
if (ice->missed_count > 5) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING, "missed too many: %d, looking for new ICE dest.\n",
ice->missed_count);
ice->rready = 0;
ok = 1;
}
@ -1039,6 +1041,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
char buf[80] = "";
char buf2[80] = "";
const char *err = "";
int i = 0;
ice->missed_count = 0;
ice->rready = 1;
@ -1049,6 +1052,21 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
host2 = switch_get_addr(buf2, sizeof(buf2), ice->addr);
port2 = switch_sockaddr_get_port(ice->addr);
for (i = 0; i <= ice->ice_params->cand_idx; i++) {
if (ice->ice_params->cands[i][ice->proto].con_port == port) {
if (!strcmp(ice->ice_params->cands[i][ice->proto].con_addr, host) &&
!strcmp(ice->ice_params->cands[i][ice->proto].cand_type, "relay")) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING,
"Skiping RELAY stun/%s/dtls port change from %s:%u to %s:%u\n", is_rtcp ? "rtcp" : "rtp",
host2, port2,
host, port);
goto end;
}
}
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_NOTICE,
"Auto Changing stun/%s/dtls port from %s:%u to %s:%u\n", is_rtcp ? "rtcp" : "rtp",
host2, port2,
@ -1056,7 +1074,8 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_addr = switch_core_strdup(rtp_session->pool, host);
ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_port = port;
ice->missed_count = 0;
switch_sockaddr_info_get(&ice->addr, host, SWITCH_UNSPEC, port, 0, rtp_session->pool);
if (!is_rtcp || rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) {
@ -1369,7 +1388,7 @@ static void send_fir(switch_rtp_t *rtp_session)
fir->ssrc = htonl(rtp_session->remote_ssrc);
fir->seq = ++rtp_session->fir_seq;
fir->r1 = fir->r2 = fir->r3 = 0;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG1, "Sending RTCP FIR %d\n", rtp_session->fir_seq);
rtcp_bytes = sizeof(switch_rtcp_ext_hdr_t) + sizeof(rtcp_fir_t);
@ -2377,6 +2396,26 @@ static int dtls_state_handshake(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
return 0;
}
static void free_dtls(switch_dtls_t **dtlsp)
{
switch_dtls_t *dtls;
if (!dtlsp) {
return;
}
dtls = *dtlsp;
*dtlsp = NULL;
if (dtls->ssl) {
SSL_free(dtls->ssl);
}
if (dtls->ssl_ctx) {
SSL_CTX_free(dtls->ssl_ctx);
}
}
static int do_dtls(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
{
int r = 0, ret = 0, len;
@ -2384,16 +2423,17 @@ static int do_dtls(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
switch_size_t bytes;
if (dtls->bytes) {
//if (dtls->state == DS_READY) {
//
//}
if ((ret = BIO_write(dtls->read_bio, dtls->data, dtls->bytes)) != (int)dtls->bytes) {
ret = SSL_get_error(dtls->ssl, ret);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS packet read err %d\n", rtp_type(rtp_session), ret);
dtls_set_state(dtls, DS_FAIL);
return -1;
}
if (dtls->state == DS_READY) {
dtls_set_state(dtls, DS_HANDSHAKE);
}
}
if (SSL_read(dtls->ssl, dtls->data, dtls->bytes) == (int)dtls->bytes) {
@ -2453,6 +2493,30 @@ SWITCH_DECLARE(int) switch_rtp_has_dtls(void) {
#endif
}
SWITCH_DECLARE(switch_status_t) switch_rtp_del_dtls(switch_rtp_t *rtp_session, dtls_type_t type)
{
if (!rtp_session->dtls && !rtp_session->rtcp_dtls) {
return SWITCH_STATUS_FALSE;
}
if ((type & DTLS_TYPE_RTP)) {
if (rtp_session->dtls && rtp_session->dtls == rtp_session->rtcp_dtls) {
rtp_session->rtcp_dtls = NULL;
}
if (rtp_session->dtls) {
free_dtls(&rtp_session->dtls);
}
}
if ((type & DTLS_TYPE_RTCP) && rtp_session->rtcp_dtls) {
free_dtls(&rtp_session->rtcp_dtls);
}
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, dtls_fingerprint_t *local_fp, dtls_fingerprint_t *remote_fp, dtls_type_t type)
{
switch_dtls_t *dtls;
@ -2471,6 +2535,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, d
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_CRIT, "INVALID TYPE!\n");
}
switch_rtp_del_dtls(rtp_session, type);
if ((type & DTLS_TYPE_RTP) && (type & DTLS_TYPE_RTCP)) {
kind = "RTP/RTCP";
} else if ((type & DTLS_TYPE_RTP)) {
@ -2487,8 +2553,6 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, d
return SWITCH_STATUS_FALSE;
}
dtls = switch_core_alloc(rtp_session->pool, sizeof(*dtls));
@ -2579,6 +2643,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, d
SSL_set_connect_state(dtls->ssl);
}
rtp_session->flags[SWITCH_RTP_FLAG_VIDEO_BREAK] = 1;
switch_rtp_break(rtp_session);
return SWITCH_STATUS_SUCCESS;
@ -3328,6 +3394,12 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_sessio
rtp_session->rtp_bugs |= RTP_BUG_ACCEPT_ANY_PACKETS;
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
rtp_session->flags[SWITCH_RTP_FLAG_VIDEO_BREAK] = 1;
switch_rtp_break(rtp_session);
}
return SWITCH_STATUS_SUCCESS;
}
@ -3360,7 +3432,10 @@ SWITCH_DECLARE(void) switch_rtp_break(switch_rtp_t *rtp_session)
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
int ret = 1;
if (rtp_session->session) {
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO_BREAK]) {
rtp_session->flags[SWITCH_RTP_FLAG_VIDEO_BREAK] = 0;
ret = 0;
} else if (rtp_session->session) {
switch_channel_t *channel = switch_core_session_get_channel(rtp_session->session);
if (switch_channel_test_flag(channel, CF_VIDEO_BREAK)) {
switch_channel_clear_flag(channel, CF_VIDEO_BREAK);
@ -3369,6 +3444,8 @@ SWITCH_DECLARE(void) switch_rtp_break(switch_rtp_t *rtp_session)
}
if (ret) return;
switch_rtp_video_refresh(rtp_session);
}
switch_mutex_lock(rtp_session->flag_mutex);
@ -3429,27 +3506,6 @@ SWITCH_DECLARE(uint8_t) switch_rtp_ready(switch_rtp_t *rtp_session)
return ret;
}
static void free_dtls(switch_dtls_t **dtlsp)
{
switch_dtls_t *dtls;
if (!dtlsp) {
return;
}
dtls = *dtlsp;
*dtlsp = NULL;
if (dtls->ssl) {
SSL_free(dtls->ssl);
}
if (dtls->ssl_ctx) {
SSL_CTX_free(dtls->ssl_ctx);
}
}
SWITCH_DECLARE(void) switch_rtp_destroy(switch_rtp_t **rtp_session)
{
void *pop;
@ -4635,7 +4691,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
pt = 100000;
}
poll_status = switch_poll(rtp_session->read_pollfd, 1, &fdr, pt);
@ -4651,10 +4707,12 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
}
if (poll_status == SWITCH_STATUS_SUCCESS) {
if (read_pretriggered) {
read_pretriggered = 0;
} else {
status = read_rtp_packet(rtp_session, &bytes, flags, SWITCH_TRUE);
if (status == SWITCH_STATUS_GENERR) {