mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-07-24 05:02:10 +00:00
Merge branch 'staging-1.9'
This commit is contained in:
@@ -1140,7 +1140,7 @@ SWITCH_STANDARD_APP(record_av_function)
|
||||
switch_core_timer_destroy(&timer);
|
||||
}
|
||||
|
||||
switch_core_media_end_video_function(session);
|
||||
switch_core_media_end_engine_function(session, SWITCH_MEDIA_TYPE_VIDEO);
|
||||
switch_core_session_set_read_codec(session, NULL);
|
||||
switch_core_codec_destroy(&codec);
|
||||
|
||||
|
||||
@@ -3066,6 +3066,61 @@ SWITCH_STANDARD_API(uuid_chat)
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#define UUID_CAPTURE_TEXT_SYNTAX "<uuid> <on|off>"
|
||||
SWITCH_STANDARD_API(uuid_capture_text)
|
||||
{
|
||||
switch_core_session_t *tsession = NULL;
|
||||
char *uuid = NULL, *onoff = NULL;
|
||||
|
||||
if (!zstr(cmd) && (uuid = strdup(cmd))) {
|
||||
if ((onoff = strchr(uuid, ' '))) {
|
||||
*onoff++ = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (zstr(uuid) || zstr(onoff)) {
|
||||
stream->write_function(stream, "-USAGE: %s\n", UUID_CAPTURE_TEXT_SYNTAX);
|
||||
} else {
|
||||
if ((tsession = switch_core_session_locate(uuid))) {
|
||||
switch_ivr_capture_text(tsession, switch_true(onoff));
|
||||
} else {
|
||||
stream->write_function(stream, "-ERR No such channel %s!\n", uuid);
|
||||
}
|
||||
}
|
||||
|
||||
switch_safe_free(uuid);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#define UUID_SEND_TEXT_SYNTAX "<uuid> <text>"
|
||||
SWITCH_STANDARD_API(uuid_send_text)
|
||||
{
|
||||
switch_core_session_t *tsession = NULL;
|
||||
char *uuid = NULL, *text = NULL;
|
||||
|
||||
if (!zstr(cmd) && (uuid = strdup(cmd))) {
|
||||
if ((text = strchr(uuid, ' '))) {
|
||||
*text++ = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (zstr(uuid) || zstr(text)) {
|
||||
stream->write_function(stream, "-USAGE: %s\n", UUID_SEND_TEXT_SYNTAX);
|
||||
} else {
|
||||
if ((tsession = switch_core_session_locate(uuid))) {
|
||||
switch_core_session_print(tsession, text);
|
||||
switch_core_session_print(tsession, "\r\n");
|
||||
switch_core_session_rwunlock(tsession);
|
||||
} else {
|
||||
stream->write_function(stream, "-ERR No such channel %s!\n", uuid);
|
||||
}
|
||||
}
|
||||
|
||||
switch_safe_free(uuid);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#define UUID_DROP_DTMF_SYNTAX "<uuid> [on | off ] [ mask_digits <digits> | mask_file <file>]"
|
||||
SWITCH_STANDARD_API(uuid_drop_dtmf)
|
||||
{
|
||||
@@ -7197,6 +7252,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_broadcast", "Execute dialplan application", uuid_broadcast_function, BROADCAST_SYNTAX);
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_buglist", "List media bugs on a session", uuid_buglist_function, BUGLIST_SYNTAX);
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_chat", "Send a chat message", uuid_chat, UUID_CHAT_SYNTAX);
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_send_text", "Send text in real-time", uuid_send_text, UUID_SEND_TEXT_SYNTAX);
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_capture_text", "start/stop capture_text", uuid_capture_text, UUID_CAPTURE_TEXT_SYNTAX);
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_codec_debug", "Send codec a debug message", uuid_codec_debug_function, CODEC_DEBUG_SYNTAX);
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_codec_param", "Send codec a param", uuid_codec_param_function, CODEC_PARAM_SYNTAX);
|
||||
SWITCH_ADD_API(commands_api_interface, "uuid_debug_media", "Debug media", uuid_debug_media_function, DEBUG_MEDIA_SYNTAX);
|
||||
@@ -7376,6 +7433,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
|
||||
switch_console_set_complete("add uuid_broadcast ::console::list_uuid");
|
||||
switch_console_set_complete("add uuid_buglist ::console::list_uuid");
|
||||
switch_console_set_complete("add uuid_chat ::console::list_uuid");
|
||||
switch_console_set_complete("add uuid_send_text ::console::list_uuid");
|
||||
switch_console_set_complete("add uuid_capture_text ::console::list_uuid");
|
||||
switch_console_set_complete("add uuid_codec_debug ::console::list_uuid audio");
|
||||
switch_console_set_complete("add uuid_codec_debug ::console::list_uuid video");
|
||||
switch_console_set_complete("add uuid_codec_param ::console::list_uuid audio read");
|
||||
@@ -7439,6 +7498,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
|
||||
switch_console_set_complete("add file_exists");
|
||||
switch_console_set_complete("add getcputime");
|
||||
|
||||
switch_msrp_load_apis_and_applications(module_interface);
|
||||
|
||||
/* indicate that the module should continue to be loaded */
|
||||
return SWITCH_STATUS_NOUNLOAD;
|
||||
}
|
||||
|
||||
@@ -1148,6 +1148,13 @@ switch_status_t conference_member_del(conference_obj_t *conference, conference_m
|
||||
lock_member(member);
|
||||
conference_utils_member_clear_flag(member, MFLAG_INTREE);
|
||||
|
||||
|
||||
switch_safe_free(member->text_framedata);
|
||||
member->text_framesize = 0;
|
||||
if (member->text_buffer) {
|
||||
switch_buffer_destroy(&member->text_buffer);
|
||||
}
|
||||
|
||||
if (member->rec) {
|
||||
conference->recording_members--;
|
||||
}
|
||||
|
||||
@@ -249,6 +249,42 @@ void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, void *ob
|
||||
|
||||
floor_holder = conference->floor_holder;
|
||||
|
||||
for (imember = conference->members; imember; imember = imember->next) {
|
||||
if (!zstr(imember->text_framedata)) {
|
||||
switch_frame_t frame = { 0 };
|
||||
char *framedata;
|
||||
uint32_t framedatalen;
|
||||
const char *caller_id_name = switch_channel_get_variable(imember->channel, "caller_id_name");
|
||||
unsigned char CR[3] = TEXT_UNICODE_LINEFEED;
|
||||
|
||||
|
||||
switch_mutex_lock(imember->text_mutex);
|
||||
|
||||
framedatalen = strlen(imember->text_framedata) + strlen(caller_id_name) + 6;
|
||||
|
||||
switch_zmalloc(framedata, framedatalen);
|
||||
|
||||
switch_snprintf(framedata, framedatalen, "%s::\n%s", caller_id_name, imember->text_framedata);
|
||||
memcpy(framedata + strlen(framedata), CR, sizeof(CR));
|
||||
|
||||
|
||||
frame.data = framedata;
|
||||
frame.datalen = framedatalen;
|
||||
|
||||
for (omember = conference->members; omember; omember = omember->next) {
|
||||
if (omember != imember) {
|
||||
switch_core_session_write_text_frame(omember->session, &frame, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
free(framedata);
|
||||
|
||||
imember->text_framedata[0] = '\0';
|
||||
|
||||
switch_mutex_unlock(imember->text_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read one frame of audio from each member channel and save it for redistribution */
|
||||
for (imember = conference->members; imember; imember = imember->next) {
|
||||
uint32_t buf_read = 0;
|
||||
@@ -1610,6 +1646,65 @@ SWITCH_STANDARD_APP(conference_auto_function)
|
||||
}
|
||||
|
||||
|
||||
switch_status_t conference_text_thread_callback(switch_core_session_t *session, switch_frame_t *frame, void *user_data)
|
||||
{
|
||||
conference_member_t *member = (conference_member_t *)user_data;
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
switch_size_t inuse = 0;
|
||||
|
||||
if (!member) return SWITCH_STATUS_FALSE;
|
||||
|
||||
|
||||
switch_mutex_lock(member->text_mutex);
|
||||
if (!member->text_buffer) {
|
||||
switch_buffer_create_dynamic(&member->text_buffer, 512, 1024, 0);
|
||||
switch_zmalloc(member->text_framedata, 1024);
|
||||
member->text_framesize = 1024;
|
||||
}
|
||||
|
||||
if (frame->data && frame->datalen && !(frame->flags & SFF_CNG)) {
|
||||
switch_buffer_write(member->text_buffer, frame->data, frame->datalen);
|
||||
}
|
||||
|
||||
inuse = switch_buffer_inuse(member->text_buffer);
|
||||
|
||||
if (zstr(member->text_framedata) && inuse && (switch_channel_test_flag(channel, CF_TEXT_IDLE) || switch_test_flag(frame, SFF_TEXT_LINE_BREAK))) {
|
||||
int bytes = 0, ok = 0;
|
||||
char *p;
|
||||
|
||||
if (inuse + 1 > member->text_framesize) {
|
||||
void *tmp = malloc(inuse + 1024);
|
||||
memcpy(tmp, member->text_framedata, member->text_framesize);
|
||||
|
||||
switch_assert(tmp);
|
||||
|
||||
member->text_framesize = inuse + 1024;
|
||||
|
||||
free(member->text_framedata);
|
||||
member->text_framedata = tmp;
|
||||
|
||||
}
|
||||
|
||||
bytes = switch_buffer_read(member->text_buffer, member->text_framedata, inuse);
|
||||
*(member->text_framedata + bytes) = '\0';
|
||||
|
||||
for(p = member->text_framedata; p && *p; p++) {
|
||||
if (*p > 32 && *p < 127) {
|
||||
ok++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
member->text_framedata[0] = '\0';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
switch_mutex_unlock(member->text_mutex);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Application interface function that is called from the dialplan to join the channel to a conference */
|
||||
SWITCH_STANDARD_APP(conference_function)
|
||||
{
|
||||
@@ -2123,6 +2218,7 @@ SWITCH_STANDARD_APP(conference_function)
|
||||
switch_mutex_init(&member.fnode_mutex, SWITCH_MUTEX_NESTED, member.pool);
|
||||
switch_mutex_init(&member.audio_in_mutex, SWITCH_MUTEX_NESTED, member.pool);
|
||||
switch_mutex_init(&member.audio_out_mutex, SWITCH_MUTEX_NESTED, member.pool);
|
||||
switch_mutex_init(&member.text_mutex, SWITCH_MUTEX_NESTED, member.pool);
|
||||
switch_thread_rwlock_create(&member.rwlock, member.pool);
|
||||
|
||||
if (conference_member_setup_media(&member, conference)) {
|
||||
@@ -2197,6 +2293,7 @@ SWITCH_STANDARD_APP(conference_function)
|
||||
|
||||
/* Chime in the core video thread */
|
||||
switch_core_session_set_video_read_callback(session, conference_video_thread_callback, (void *)&member);
|
||||
switch_core_session_set_text_read_callback(session, conference_text_thread_callback, (void *)&member);
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_VIDEO_ONLY)) {
|
||||
while(conference_utils_member_test_flag((&member), MFLAG_RUNNING) && switch_channel_ready(channel)) {
|
||||
@@ -2211,6 +2308,7 @@ SWITCH_STANDARD_APP(conference_function)
|
||||
}
|
||||
|
||||
switch_core_session_set_video_read_callback(session, NULL, NULL);
|
||||
switch_core_session_set_text_read_callback(session, NULL, NULL);
|
||||
|
||||
switch_channel_set_private(channel, "_conference_autocall_list_", NULL);
|
||||
|
||||
|
||||
@@ -790,6 +790,13 @@ struct conference_member {
|
||||
int reset_media;
|
||||
int flip;
|
||||
int flip_count;
|
||||
|
||||
switch_mutex_t *text_mutex;
|
||||
switch_buffer_t *text_buffer;
|
||||
char *text_framedata;
|
||||
uint32_t text_framesize;
|
||||
|
||||
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
@@ -971,6 +978,7 @@ void conference_video_fnode_check(conference_file_node_t *fnode, int canvas_id);
|
||||
switch_status_t conference_video_set_canvas_bgimg(mcu_canvas_t *canvas, const char *img_path);
|
||||
switch_status_t conference_al_parse_position(al_handle_t *al, const char *data);
|
||||
switch_status_t conference_video_thread_callback(switch_core_session_t *session, switch_frame_t *frame, void *user_data);
|
||||
switch_status_t conference_text_thread_callback(switch_core_session_t *session, switch_frame_t *frame, void *user_data);
|
||||
void *SWITCH_THREAD_FUNC conference_video_muxing_write_thread_run(switch_thread_t *thread, void *obj);
|
||||
void conference_member_check_agc_levels(conference_member_t *member);
|
||||
void conference_member_clear_avg(conference_member_t *member);
|
||||
|
||||
@@ -1012,6 +1012,10 @@ SWITCH_STANDARD_APP(set_mute_function)
|
||||
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_APP(capture_text_function)
|
||||
{
|
||||
switch_ivr_capture_text(session, switch_true((char *)data));
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_APP(ring_ready_function)
|
||||
{
|
||||
@@ -6127,6 +6131,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
|
||||
SWITCH_ADD_CHAT(chat_interface, "event", event_chat_send);
|
||||
SWITCH_ADD_CHAT(chat_interface, "api", api_chat_send);
|
||||
|
||||
|
||||
SWITCH_ADD_API(api_interface, "strepoch", "Convert a date string into epoch time", strepoch_api_function, "<string>");
|
||||
SWITCH_ADD_API(api_interface, "page", "Send a file as a page", page_api_function, "(var1=val1,var2=val2)<var1=val1,var2=val2><chan1>[:_:<chanN>]");
|
||||
SWITCH_ADD_API(api_interface, "strmicroepoch", "Convert a date string into micoepoch time", strmicroepoch_api_function, "<string>");
|
||||
@@ -6216,6 +6221,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
|
||||
SWITCH_ADD_APP(app_interface, "multiunset", "Unset many channel variables", SET_LONG_DESC, multiunset_function, "[^^<delim>]<varname> <var2> <var3>",
|
||||
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
|
||||
|
||||
SWITCH_ADD_APP(app_interface, "capture_text", "capture text", "capture text", capture_text_function, "", SAF_NONE);
|
||||
SWITCH_ADD_APP(app_interface, "ring_ready", "Indicate Ring_Ready", "Indicate Ring_Ready on a channel.", ring_ready_function, "", SAF_SUPPORT_NOMEDIA);
|
||||
SWITCH_ADD_APP(app_interface, "remove_bugs", "Remove media bugs", "Remove all media bugs from a channel.", remove_bugs_function, "[<function>]", SAF_NONE);
|
||||
SWITCH_ADD_APP(app_interface, "break", "Break", "Set the break flag.", break_function, "", SAF_SUPPORT_NOMEDIA);
|
||||
|
||||
@@ -183,7 +183,7 @@ SWITCH_STANDARD_APP(record_fsv_function)
|
||||
switch_mutex_init(&mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
|
||||
eh.mutex = mutex;
|
||||
eh.fd = fd;
|
||||
switch_core_media_start_video_function(session, record_video_thread, &eh);
|
||||
switch_core_media_start_engine_function(session, SWITCH_MEDIA_TYPE_VIDEO, record_video_thread, &eh);
|
||||
}
|
||||
|
||||
|
||||
@@ -257,7 +257,7 @@ SWITCH_STANDARD_APP(record_fsv_function)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
switch_core_media_end_video_function(session);
|
||||
switch_core_media_end_engine_function(session, SWITCH_MEDIA_TYPE_VIDEO);
|
||||
switch_core_session_set_read_codec(session, NULL);
|
||||
switch_core_codec_destroy(&codec);
|
||||
|
||||
@@ -751,7 +751,7 @@ SWITCH_STANDARD_APP(decode_video_function)
|
||||
|
||||
switch_channel_set_flag(channel, CF_VIDEO_DECODED_READ);
|
||||
|
||||
switch_core_media_start_video_function(session, decode_video_thread, &max_pictures);
|
||||
switch_core_media_start_engine_function(session, SWITCH_MEDIA_TYPE_VIDEO, decode_video_thread, &max_pictures);
|
||||
|
||||
switch_ivr_play_file(session, NULL, moh, NULL);
|
||||
|
||||
@@ -762,7 +762,7 @@ SWITCH_STANDARD_APP(decode_video_function)
|
||||
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "OK");
|
||||
|
||||
|
||||
switch_core_media_end_video_function(session);
|
||||
switch_core_media_end_engine_function(session, SWITCH_MEDIA_TYPE_VIDEO);
|
||||
switch_core_session_video_reset(session);
|
||||
}
|
||||
|
||||
|
||||
@@ -287,6 +287,8 @@ switch_io_routines_t rtc_io_routines = {
|
||||
/*.state_change */ NULL,
|
||||
/*.read_video_frame */ rtc_read_video_frame,
|
||||
/*.write_video_frame */ rtc_write_video_frame,
|
||||
/*.read_text_frame */ NULL,
|
||||
/*.write_text_frame */ NULL,
|
||||
/*.state_run*/ NULL,
|
||||
/*.get_jb*/ rtc_get_jb
|
||||
};
|
||||
@@ -330,6 +332,7 @@ void rtc_attach_private(switch_core_session_t *session, private_object_t *tech_p
|
||||
switch_core_media_check_dtmf_type(session);
|
||||
switch_channel_set_cap(tech_pvt->channel, CC_JITTERBUFFER);
|
||||
switch_channel_set_cap(tech_pvt->channel, CC_FS_RTP);
|
||||
switch_channel_set_cap(tech_pvt->channel, CC_IO_OVERRIDE);
|
||||
switch_media_handle_create(&tech_pvt->media_handle, session, &tech_pvt->mparams);
|
||||
switch_core_session_set_private(session, tech_pvt);
|
||||
|
||||
|
||||
@@ -62,6 +62,8 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
|
||||
static switch_status_t sofia_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
|
||||
static switch_status_t sofia_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
|
||||
static switch_status_t sofia_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
|
||||
static switch_status_t sofia_read_text_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
|
||||
static switch_status_t sofia_write_text_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
|
||||
static switch_status_t sofia_kill_channel(switch_core_session_t *session, int sig);
|
||||
|
||||
/* BODY OF THE MODULE */
|
||||
@@ -918,6 +920,33 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t sofia_read_text_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
|
||||
{
|
||||
return switch_core_media_read_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_TEXT);
|
||||
}
|
||||
|
||||
static switch_status_t sofia_write_text_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
|
||||
{
|
||||
if (switch_channel_test_flag(switch_core_session_get_channel(session), CF_MSRP)) {
|
||||
switch_msrp_session_t *msrp_session = switch_core_media_get_msrp_session(session);
|
||||
|
||||
if (frame && msrp_session) {
|
||||
switch_msrp_msg_t msrp_msg = { 0 };
|
||||
|
||||
msrp_msg.headers[MSRP_H_CONTENT_TYPE] = "message/cpim";
|
||||
// msrp_msg.headers[MSRP_H_CONTENT_TYPE] = "text/plain";
|
||||
msrp_msg.payload = frame->data;
|
||||
msrp_msg.payload_bytes = frame->datalen;
|
||||
|
||||
return switch_msrp_send(msrp_session, &msrp_msg);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
return switch_core_media_write_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_TEXT);
|
||||
}
|
||||
|
||||
static switch_status_t sofia_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
|
||||
{
|
||||
private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
|
||||
@@ -4279,6 +4308,8 @@ switch_io_routines_t sofia_io_routines = {
|
||||
/*.state_change */ NULL,
|
||||
/*.read_video_frame */ sofia_read_video_frame,
|
||||
/*.write_video_frame */ sofia_write_video_frame,
|
||||
/*.read_text_frame */ sofia_read_text_frame,
|
||||
/*.write_text_frame */ sofia_write_text_frame,
|
||||
/*.state_run*/ NULL,
|
||||
/*.get_jb*/ sofia_get_jb
|
||||
};
|
||||
|
||||
@@ -122,6 +122,8 @@ switch_io_routines_t crtp_io_routines = {
|
||||
/*state_change*/ NULL,
|
||||
/*read_video_frame*/ NULL,
|
||||
/*write_video_frame*/ NULL,
|
||||
/*read_text_frame*/ NULL,
|
||||
/*write_text_frame*/ NULL,
|
||||
/*state_run*/ NULL
|
||||
|
||||
|
||||
|
||||
@@ -159,6 +159,8 @@ void sofia_glue_attach_private(switch_core_session_t *session, sofia_profile_t *
|
||||
switch_channel_set_cap(tech_pvt->channel, CC_PROXY_MEDIA);
|
||||
switch_channel_set_cap(tech_pvt->channel, CC_JITTERBUFFER);
|
||||
switch_channel_set_cap(tech_pvt->channel, CC_FS_RTP);
|
||||
switch_channel_set_cap(tech_pvt->channel, CC_RTP_RTT);
|
||||
switch_channel_set_cap(tech_pvt->channel, CC_MSRP);
|
||||
switch_channel_set_cap(tech_pvt->channel, CC_QUEUEABLE_DTMF_DELAY);
|
||||
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
#include <poll.h>
|
||||
#define closesocket(x) close(x)
|
||||
#endif
|
||||
#include <switch_utils.h>
|
||||
#include <switch.h>
|
||||
#include "mcast.h"
|
||||
|
||||
|
||||
|
||||
@@ -130,6 +130,10 @@ static switch_bool_t check_name(const char *name)
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t verto_read_text_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
|
||||
static switch_status_t verto_write_text_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
|
||||
static void set_text_funcs(switch_core_session_t *session);
|
||||
|
||||
static verto_profile_t *find_profile(const char *name);
|
||||
static jsock_t *get_jsock(const char *uuid);
|
||||
|
||||
@@ -2116,6 +2120,11 @@ switch_endpoint_interface_t *verto_endpoint_interface = NULL;
|
||||
|
||||
static switch_status_t verto_on_destroy(switch_core_session_t *session)
|
||||
{
|
||||
verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
|
||||
|
||||
switch_buffer_destroy(&tech_pvt->text_read_buffer);
|
||||
switch_buffer_destroy(&tech_pvt->text_write_buffer);
|
||||
|
||||
UNPROTECT_INTERFACE(verto_endpoint_interface);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
@@ -2576,6 +2585,7 @@ static int verto_recover_callback(switch_core_session_t *session)
|
||||
}
|
||||
|
||||
tech_pvt = switch_core_session_alloc(session, sizeof(*tech_pvt));
|
||||
tech_pvt->pool = switch_core_session_get_pool(session);
|
||||
tech_pvt->session = session;
|
||||
tech_pvt->channel = channel;
|
||||
tech_pvt->jsock_uuid = (char *) jsock_uuid_str;
|
||||
@@ -3261,7 +3271,7 @@ static void parse_user_vars(cJSON *obj, switch_core_session_t *session)
|
||||
|
||||
static switch_bool_t verto__info_func(const char *method, cJSON *params, jsock_t *jsock, cJSON **response)
|
||||
{
|
||||
cJSON *msg = NULL, *dialog = NULL;
|
||||
cJSON *msg = NULL, *dialog = NULL, *txt = NULL;
|
||||
const char *call_id = NULL, *dtmf = NULL;
|
||||
switch_bool_t r = SWITCH_TRUE;
|
||||
char *proto = VERTO_CHAT_PROTO;
|
||||
@@ -3298,6 +3308,43 @@ static switch_bool_t verto__info_func(const char *method, cJSON *params, jsock_t
|
||||
}
|
||||
}
|
||||
|
||||
if ((txt = cJSON_GetObjectItem(params, "txt"))) {
|
||||
switch_core_session_t *session;
|
||||
|
||||
if ((session = switch_core_session_locate(call_id))) {
|
||||
verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
|
||||
char charbuf[2] = "";
|
||||
char *chardata = NULL;
|
||||
cJSON *data;
|
||||
|
||||
if ((data = cJSON_GetObjectItem(txt, "code"))) {
|
||||
charbuf[0] = data->valueint;
|
||||
chardata = charbuf;
|
||||
} else if ((data = cJSON_GetObjectItem(txt, "chars"))) {
|
||||
if (data->valuestring) {
|
||||
chardata = data->valuestring;
|
||||
} else if (data->valueint) {
|
||||
charbuf[0] = data->valueint;
|
||||
chardata = charbuf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (chardata) {
|
||||
switch_mutex_lock(tech_pvt->text_read_mutex);
|
||||
switch_buffer_write(tech_pvt->text_read_buffer, chardata, strlen(chardata));
|
||||
switch_mutex_unlock(tech_pvt->text_read_mutex);
|
||||
|
||||
if ((switch_mutex_trylock(tech_pvt->text_cond_mutex) == SWITCH_STATUS_SUCCESS)) {
|
||||
switch_thread_cond_signal(tech_pvt->text_cond);
|
||||
switch_mutex_unlock(tech_pvt->text_cond_mutex);
|
||||
}
|
||||
}
|
||||
switch_core_session_rwunlock(session);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ((msg = cJSON_GetObjectItem(params, "msg"))) {
|
||||
switch_event_t *event;
|
||||
char *to = (char *) cJSON_GetObjectCstr(msg, "to");
|
||||
@@ -3380,6 +3427,8 @@ static switch_bool_t verto__info_func(const char *method, cJSON *params, jsock_t
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static switch_bool_t verto__invite_func(const char *method, cJSON *params, jsock_t *jsock, cJSON **response)
|
||||
{
|
||||
cJSON *obj = cJSON_CreateObject(), *screenShare = NULL, *dedEnc = NULL, *mirrorInput, *bandwidth = NULL, *canvas = NULL;
|
||||
@@ -3431,12 +3480,13 @@ static switch_bool_t verto__invite_func(const char *method, cJSON *params, jsock
|
||||
|
||||
tech_pvt = switch_core_session_alloc(session, sizeof(*tech_pvt));
|
||||
tech_pvt->session = session;
|
||||
tech_pvt->pool = switch_core_session_get_pool(session);
|
||||
tech_pvt->channel = channel;
|
||||
tech_pvt->jsock_uuid = switch_core_session_strdup(session, jsock->uuid_str);
|
||||
tech_pvt->r_sdp = switch_core_session_strdup(session, sdp);
|
||||
switch_core_media_set_sdp_codec_string(session, sdp, SDP_TYPE_REQUEST);
|
||||
switch_core_session_set_private_class(session, tech_pvt, SWITCH_PVT_SECONDARY);
|
||||
|
||||
set_text_funcs(session);
|
||||
|
||||
tech_pvt->call_id = switch_core_session_strdup(session, call_id);
|
||||
if ((tech_pvt->smh = switch_core_session_get_media_handle(session))) {
|
||||
@@ -5042,6 +5092,115 @@ switch_io_routines_t verto_io_routines = {
|
||||
/*.outgoing_channel */ verto_outgoing_channel
|
||||
};
|
||||
|
||||
|
||||
switch_io_routines_t verto_io_override = {
|
||||
/*.outgoing_channel */ NULL,
|
||||
/*.read_frame */ NULL,
|
||||
/*.write_frame */ NULL,
|
||||
/*.kill_channel */ NULL,
|
||||
/*.send_dtmf */ NULL,
|
||||
/*.receive_message */ NULL,
|
||||
/*.receive_event */ NULL,
|
||||
/*.state_change */ NULL,
|
||||
/*.read_video_frame */ NULL,
|
||||
/*.write_video_frame */ NULL,
|
||||
/*.read_text_frame */ verto_read_text_frame,
|
||||
/*.write_text_frame */ verto_write_text_frame,
|
||||
/*.state_run*/ NULL,
|
||||
/*.get_jb*/ NULL
|
||||
};
|
||||
|
||||
|
||||
static switch_status_t verto_read_text_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
|
||||
{
|
||||
verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
|
||||
switch_status_t status;
|
||||
|
||||
switch_mutex_lock(tech_pvt->text_cond_mutex);
|
||||
|
||||
status = switch_thread_cond_timedwait(tech_pvt->text_cond, tech_pvt->text_cond_mutex, 100000);
|
||||
switch_mutex_unlock(tech_pvt->text_cond_mutex);
|
||||
|
||||
*frame = &tech_pvt->text_read_frame;
|
||||
(*frame)->flags = 0;
|
||||
|
||||
switch_mutex_lock(tech_pvt->text_read_mutex);
|
||||
if (switch_buffer_inuse(tech_pvt->text_read_buffer)) {
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
tech_pvt->text_read_frame.datalen = switch_buffer_read(tech_pvt->text_read_buffer, tech_pvt->text_read_frame.data, 100);
|
||||
} else {
|
||||
(*frame)->flags |= SFF_CNG;
|
||||
tech_pvt->text_read_frame.datalen = 2;
|
||||
status = SWITCH_STATUS_BREAK;
|
||||
}
|
||||
switch_mutex_unlock(tech_pvt->text_read_mutex);
|
||||
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t verto_write_text_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
|
||||
{
|
||||
verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
|
||||
|
||||
switch_mutex_lock(tech_pvt->text_write_mutex);
|
||||
|
||||
|
||||
if (frame) {
|
||||
switch_buffer_write(tech_pvt->text_write_buffer, frame->data, frame->datalen);
|
||||
}
|
||||
|
||||
if (switch_buffer_inuse(tech_pvt->text_write_buffer)) {
|
||||
uint32_t datalen;
|
||||
switch_byte_t data[SWITCH_RTP_MAX_BUF_LEN] = "";
|
||||
|
||||
if ((datalen = switch_buffer_read(tech_pvt->text_write_buffer, data, 100))) {
|
||||
cJSON *obj = NULL, *txt = NULL, *params = NULL;
|
||||
jsock_t *jsock;
|
||||
|
||||
obj = jrpc_new_req("verto.info", tech_pvt->call_id, ¶ms);
|
||||
txt = json_add_child_obj(params, "txt", NULL);
|
||||
cJSON_AddItemToObject(txt, "chars", cJSON_CreateString((char *)data));
|
||||
|
||||
if ((jsock = get_jsock(tech_pvt->jsock_uuid))) {
|
||||
jsock_queue_event(jsock, &obj, SWITCH_TRUE);
|
||||
switch_thread_rwlock_unlock(jsock->rwlock);
|
||||
} else {
|
||||
cJSON_Delete(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch_mutex_unlock(tech_pvt->text_write_mutex);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void set_text_funcs(switch_core_session_t *session)
|
||||
{
|
||||
if ((switch_core_session_override_io_routines(session, &verto_io_override) == SWITCH_STATUS_SUCCESS)) {
|
||||
verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
|
||||
|
||||
tech_pvt->text_read_frame.data = tech_pvt->text_read_frame_data;
|
||||
|
||||
switch_mutex_init(&tech_pvt->text_read_mutex, SWITCH_MUTEX_NESTED, tech_pvt->pool);
|
||||
switch_mutex_init(&tech_pvt->text_write_mutex, SWITCH_MUTEX_NESTED, tech_pvt->pool);
|
||||
switch_mutex_init(&tech_pvt->text_cond_mutex, SWITCH_MUTEX_NESTED, tech_pvt->pool);
|
||||
switch_thread_cond_create(&tech_pvt->text_cond, tech_pvt->pool);
|
||||
|
||||
switch_buffer_create_dynamic(&tech_pvt->text_read_buffer, 512, 1024, 0);
|
||||
switch_buffer_create_dynamic(&tech_pvt->text_write_buffer, 512, 1024, 0);
|
||||
|
||||
switch_channel_set_flag(switch_core_session_get_channel(session), CF_TEXT);
|
||||
switch_core_session_start_text_thread(session);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static char *verto_get_dial_string(const char *uid, switch_stream_handle_t *rstream)
|
||||
{
|
||||
jsock_t *jsock;
|
||||
@@ -5187,11 +5346,14 @@ static switch_call_cause_t verto_outgoing_channel(switch_core_session_t *session
|
||||
char name[512];
|
||||
|
||||
tech_pvt = switch_core_session_alloc(*new_session, sizeof(*tech_pvt));
|
||||
tech_pvt->pool = switch_core_session_get_pool(*new_session);
|
||||
tech_pvt->session = *new_session;
|
||||
tech_pvt->channel = channel;
|
||||
tech_pvt->jsock_uuid = switch_core_session_strdup(*new_session, jsock_uuid_str);
|
||||
|
||||
switch_core_session_set_private_class(*new_session, tech_pvt, SWITCH_PVT_SECONDARY);
|
||||
|
||||
set_text_funcs(*new_session);
|
||||
|
||||
if (session) {
|
||||
switch_channel_t *ochannel = switch_core_session_get_channel(session);
|
||||
|
||||
|
||||
@@ -173,6 +173,7 @@ typedef enum {
|
||||
} tflag_t;
|
||||
|
||||
typedef struct verto_pvt_s {
|
||||
switch_memory_pool_t *pool;
|
||||
char *jsock_uuid;
|
||||
char *call_id;
|
||||
char *r_sdp;
|
||||
@@ -184,6 +185,17 @@ typedef struct verto_pvt_s {
|
||||
switch_call_cause_t remote_hangup_cause;
|
||||
time_t detach_time;
|
||||
struct verto_pvt_s *next;
|
||||
switch_byte_t text_read_frame_data[SWITCH_RTP_MAX_BUF_LEN];
|
||||
switch_frame_t text_read_frame;
|
||||
|
||||
switch_thread_cond_t *text_cond;
|
||||
switch_mutex_t *text_cond_mutex;
|
||||
switch_mutex_t *text_read_mutex;
|
||||
switch_mutex_t *text_write_mutex;
|
||||
|
||||
switch_buffer_t *text_read_buffer;
|
||||
switch_buffer_t *text_write_buffer;
|
||||
|
||||
} verto_pvt_t;
|
||||
|
||||
typedef struct verto_vhost_s {
|
||||
|
||||
Reference in New Issue
Block a user