some refactoring and plumbing for 1.4
This commit is contained in:
parent
c7ccf84a14
commit
4a172402d2
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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++;
|
||||
|
||||
|
|
|
@ -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++;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
126
src/switch_rtp.c
126
src/switch_rtp.c
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue