Merge branch 'master' into v1.4.beta

This commit is contained in:
Ken Rice
2013-07-12 12:48:21 -05:00
15 changed files with 749 additions and 145 deletions
+2
View File
@@ -558,11 +558,13 @@ opal
/spandsp/src/Makefile.in
/spandsp/src/make_math_fixed_tables
/spandsp/src/make_modem_filter
/spandsp/src/make_t43_gray_code_tables
/spandsp/src/math_fixed_tables.h
/spandsp/src/msvc/All/BuildLog make_at_dictionary.htm
/spandsp/src/msvc/All/BuildLog make_modem_filter.htm
/spandsp/src/spandsp.h
/spandsp/src/stamp-h1
/spandsp/src/t43_gray_code_tables.h
/spandsp/src/v17_v32bis_rx_fixed_rrc.h
/spandsp/src/v17_v32bis_rx_floating_rrc.h
/spandsp/src/v17_v32bis_tx_fixed_rrc.h
+1 -1
View File
@@ -1 +1 @@
Wed Jul 3 11:09:02 CDT 2013
Thu Jul 11 17:38:06 CDT 2013
@@ -590,7 +590,7 @@ static void print_media(sdp_printer_t *p,
case sdp_proto_udp: proto = "udp"; break;
case sdp_proto_rtp: proto = "RTP/AVP"; break;
case sdp_proto_srtp: proto = "RTP/SAVP"; break;
case sdp_proto_extended_srtp: proto = "RTP/SAVPF"; break;
//case sdp_proto_extended_srtp: proto = "RTP/SAVPF"; break;
case sdp_proto_udptl: proto = "udptl"; break;
case sdp_proto_msrp: proto = "TCP/MSRP"; break;
case sdp_proto_msrps: proto = "TCP/TLS/MSRP"; break;
+1
View File
@@ -139,6 +139,7 @@ SWITCH_DECLARE(void) switch_rtp_shutdown(void);
SWITCH_DECLARE(switch_port_t) switch_rtp_set_start_port(switch_port_t port);
SWITCH_DECLARE(switch_status_t) switch_rtp_set_ssrc(switch_rtp_t *rtp_session, uint32_t ssrc);
SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_ssrc(switch_rtp_t *rtp_session, uint32_t ssrc);
/*!
\brief Set/Get RTP end port
+1
View File
@@ -1326,6 +1326,7 @@ typedef enum {
CF_DTLS_OK,
CF_VIDEO_PASSIVE,
CF_NOVIDEO,
CF_VIDEO_ECHO,
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
/* IF YOU ADD NEW ONES CHECK IF THEY SHOULD PERSIST OR ZERO THEM IN switch_core_session.c switch_core_session_request_xml() */
CF_FLAG_MAX
+15 -9
View File
@@ -598,31 +598,39 @@ switch_mutex_unlock(obj->flag_mutex);
#define switch_set_string(_dst, _src) switch_copy_string(_dst, _src, sizeof(_dst))
SWITCH_DECLARE(char *) switch_url_encode(const char *url, char *buf, size_t len);
SWITCH_DECLARE(char *) switch_url_decode(char *s);
static inline char *switch_sanitize_number(char *number)
{
char *p = number, *q;
char *p, *q;
char warp[] = "/:";
int i;
char *val;
switch_assert(number);
if (!(strchr(p, '/') || strchr(p, ':') || strchr(p, '@') || strchr(p, '%'))) {
p = strdup(number);
val = p;
switch_url_decode(val);
if (!(strchr(val, '/') || strchr(val, ':') || strchr(val, '@') || strchr(val, '%'))) {
return number;
}
while ((q = strrchr(p, '@')))
while ((q = strrchr(val, '@')))
*q = '\0';
while ((q = strrchr(p, '%')))
while ((q = strrchr(val, '%')))
*q = '\0';
for (i = 0; i < (int) strlen(warp); i++) {
while (p && (q = strchr(p, warp[i])))
p = q + 1;
while (val && (q = strchr(val, warp[i])))
val = q + 1;
}
free(p);
return p;
return val;
}
static inline switch_bool_t switch_string_var_check(char *s, switch_bool_t disable)
@@ -930,8 +938,6 @@ SWITCH_DECLARE(char *) switch_util_quote_shell_arg_pool(const char *string, swit
#define SWITCH_READ_ACCEPTABLE(status) (status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK)
SWITCH_DECLARE(char *) switch_url_encode(const char *url, char *buf, size_t len);
SWITCH_DECLARE(char *) switch_url_decode(char *s);
SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to,
const char *from,
const char *headers,
@@ -201,7 +201,8 @@ typedef enum {
CFLAG_VIDEO_BRIDGE = (1 << 14),
CFLAG_AUDIO_ALWAYS = (1 << 15),
CFLAG_ENDCONF_FORCED = (1 << 16),
CFLAG_RFC4579 = (1 << 17)
CFLAG_RFC4579 = (1 << 17),
CFLAG_FLOOR_CHANGE = (1 << 18)
} conf_flag_t;
typedef enum {
@@ -394,6 +395,7 @@ typedef struct conference_relationship {
struct conference_member {
uint32_t id;
switch_core_session_t *session;
switch_channel_t *channel;
conference_obj_t *conference;
switch_memory_pool_t *pool;
switch_buffer_t *audio_buffer;
@@ -1443,15 +1445,20 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
conference_send_presence(conference);
channel = switch_core_session_get_channel(member->session);
switch_channel_set_flag(channel, CF_VIDEO_PASSIVE);
switch_channel_set_variable_printf(channel, "conference_member_id", "%d", member->id);
switch_channel_set_variable_printf(channel, "conference_moderator", "%s", switch_test_flag(member, MFLAG_MOD) ? "true" : "false");
switch_channel_set_variable(channel, "conference_recording", conference->record_filename);
switch_channel_set_variable(channel, CONFERENCE_UUID_VARIABLE, conference->uuid_str);
if (switch_channel_test_flag(channel, CF_VIDEO)) {
switch_channel_clear_flag(channel, CF_VIDEO_ECHO);
/* Tell the channel to request a fresh vid frame */
switch_core_session_refresh_video(member->session);
}
if (!switch_channel_get_variable(channel, "conference_call_key")) {
char *key = switch_core_session_sprintf(member->session, "conf_%s_%s_%s",
@@ -1565,6 +1572,20 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
return status;
}
static void conference_set_floor_holder(conference_obj_t *conference, conference_member_t *member)
{
if (conference->floor_holder && conference->floor_holder != member) {
switch_channel_clear_flag(conference->floor_holder->channel, CF_VIDEO_PASSIVE);
}
if ((conference->floor_holder = member)) {
switch_channel_set_flag(member->channel, CF_VIDEO_PASSIVE);
switch_core_session_refresh_video(conference->floor_holder->session);
switch_set_flag(conference, CFLAG_FLOOR_CHANGE);
}
}
/* Gain exclusive access and remove the member from the list */
static switch_status_t conference_del_member(conference_obj_t *conference, conference_member_t *member)
{
@@ -1648,7 +1669,9 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe
}
if (member == member->conference->floor_holder) {
member->conference->floor_holder = NULL;
//member->conference->floor_holder = NULL;
conference_set_floor_holder(member->conference, NULL);
if (test_eflag(conference, EFLAG_FLOOR_CHANGE)) {
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT);
@@ -1673,7 +1696,10 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe
}
}
switch_channel_clear_flag(channel, CF_VIDEO_PASSIVE);
if (switch_channel_test_flag(channel, CF_VIDEO)) {
switch_channel_set_flag(channel, CF_VIDEO_ECHO);
switch_channel_clear_flag(channel, CF_VIDEO_PASSIVE);
}
conference_send_presence(conference);
switch_channel_set_variable(channel, "conference_call_key", NULL);
@@ -1839,19 +1865,15 @@ static void *SWITCH_THREAD_FUNC conference_video_thread_run(switch_thread_t *thr
conference_member_t *imember;
switch_frame_t *vid_frame;
switch_status_t status;
int has_vid = 1, want_refresh = 0;
int want_refresh = 0;
int yield = 0;
switch_core_session_t *session;
switch_core_session_message_t msg = { 0 };
char buf[65536];
conference->video_running = 1;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Video thread started for conference %s\n", conference->name);
/* Tell the channel to request a fresh vid frame */
msg.from = __FILE__;
msg.message_id = SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ;
while (has_vid && conference->video_running == 1 && globals.running && !switch_test_flag(conference, CFLAG_DESTRUCT)) {
while (conference->video_running == 1 && globals.running && !switch_test_flag(conference, CFLAG_DESTRUCT)) {
if (yield) {
switch_yield(yield);
yield = 0;
@@ -1887,12 +1909,21 @@ static void *SWITCH_THREAD_FUNC conference_video_thread_run(switch_thread_t *thr
goto do_continue;
}
if (vid_frame && switch_test_flag(vid_frame, SFF_CNG)) {
yield = 10000;
goto do_continue;
}
memcpy(buf, vid_frame->packet, vid_frame->packetlen);
switch_mutex_unlock(conference->mutex);
switch_mutex_lock(conference->mutex);
has_vid = 0;
want_refresh = 0;
if (switch_test_flag(conference, CFLAG_FLOOR_CHANGE)) {
switch_clear_flag(conference, CFLAG_FLOOR_CHANGE);
}
for (imember = conference->members; imember; imember = imember->next) {
switch_core_session_t *isession = imember->session;
switch_channel_t *ichannel;
@@ -1908,21 +1939,20 @@ static void *SWITCH_THREAD_FUNC conference_video_thread_run(switch_thread_t *thr
switch_channel_clear_flag(ichannel, CF_VIDEO_REFRESH_REQ);
}
if (imember->session && switch_channel_test_flag(ichannel, CF_VIDEO)) {
has_vid++;
if (isession && switch_channel_test_flag(ichannel, CF_VIDEO)) {
memcpy(vid_frame->packet, buf, vid_frame->packetlen);
switch_core_session_write_video_frame(imember->session, vid_frame, SWITCH_IO_FLAG_NONE, 0);
}
switch_core_session_rwunlock(isession);
}
if (want_refresh) {
switch_core_session_receive_message(session, &msg);
if (want_refresh && session) {
switch_core_session_refresh_video(session);
want_refresh = 0;
}
do_continue:
switch_mutex_unlock(conference->mutex);
}
@@ -2078,7 +2108,8 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
}
}
conference->floor_holder = floor_holder;
//conference->floor_holder = floor_holder;
conference_set_floor_holder(conference, floor_holder);
}
@@ -5219,7 +5250,8 @@ static switch_status_t conf_api_sub_floor(conference_member_t *member, switch_st
switch_mutex_lock(member->conference->mutex);
if (member->conference->floor_holder == member) {
member->conference->floor_holder = NULL;
//member->conference->floor_holder = NULL;
conference_set_floor_holder(member->conference, NULL);
if (test_eflag(member->conference, EFLAG_FLOOR_CHANGE)) {
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT);
conference_add_event_data(member->conference, event);
@@ -5232,7 +5264,8 @@ static switch_status_t conf_api_sub_floor(conference_member_t *member, switch_st
}
}
} else if (member->conference->floor_holder == NULL) {
member->conference->floor_holder = member;
//member->conference->floor_holder = member;
conference_set_floor_holder(member->conference, member);
if (test_eflag(member->conference, EFLAG_FLOOR_CHANGE)) {
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT);
conference_add_event_data(member->conference, event);
@@ -5272,7 +5305,8 @@ static switch_status_t conf_api_sub_enforce_floor(conference_member_t *member, s
if (member->conference->floor_holder != member) {
conference_member_t *old_member = member->conference->floor_holder;
member->conference->floor_holder = member;
//member->conference->floor_holder = member;
conference_set_floor_holder(member->conference, member);
if (test_eflag(member->conference, EFLAG_FLOOR_CHANGE)) {
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT);
conference_add_event_data(member->conference, event);
@@ -7781,6 +7815,7 @@ SWITCH_STANDARD_APP(conference_function)
}
member.session = session;
member.channel = switch_core_session_get_channel(session);
member.pool = switch_core_session_get_pool(session);
if (setup_media(&member, conference)) {
+23 -3
View File
@@ -37,7 +37,7 @@
/*****************************************************************************/
/* SKINNY FUNCTIONS */
/*****************************************************************************/
char* skinny_codec2string(enum skinny_codecs skinnycodec)
char* skinny_codec2string(skinny_codecs skinnycodec)
{
switch (skinnycodec) {
case SKINNY_CODEC_ALAW_64K:
@@ -155,8 +155,8 @@ switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req)
memcpy(request, mbuf, bytes);
#ifdef SKINNY_MEGA_DEBUG
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
"Got request: length=%d,reserved=%x,type=%x\n",
request->length,request->reserved,request->type);
"Got request: length=%d,version=%x,type=%x\n",
request->length,request->version,request->type);
#endif
if(request->length < SKINNY_MESSAGE_FIELD_SIZE) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
@@ -623,6 +623,26 @@ switch_status_t perform_send_set_speaker_mode(listener_t *listener,
return skinny_send_reply_quiet(listener, message);
}
switch_status_t perform_send_srvreq_response(listener_t *listener,
const char *file, const char *func, int line,
char *ip, uint32_t port)
{
skinny_message_t *message;
message = switch_core_alloc(listener->pool, 12+sizeof(message->data.serv_res_mess));
message->type = SERVER_RESPONSE_MESSAGE;
message->length = 4 + sizeof(message->data.serv_res_mess);
message->data.serv_res_mess.serverListenPort[0] = port;
switch_inet_pton(AF_INET,ip, &message->data.serv_res_mess.serverIpAddr[0]);
switch_copy_string(message->data.serv_res_mess.server[0].serverName,ip,sizeof(message->data.serv_res_mess.server[0].serverName));
skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,
"Sending Server Request Response with IP (%s) and Port (%d)\n", ip, port);
return skinny_send_reply(listener, message);
}
switch_status_t perform_send_start_media_transmission(listener_t *listener,
const char *file, const char *func, int line,
uint32_t conference_id,
+215 -41
View File
@@ -36,6 +36,53 @@
/* mod_skinny.h should be loaded first */
#include "mod_skinny.h"
/*****************************************************************************/
/* SKINNY TYPES */
/*****************************************************************************/
typedef enum {
SKINNY_CODEC_NONE = 0,
SKINNY_CODEC_NONSTANDARD = 1,
SKINNY_CODEC_ALAW_64K = 2,
SKINNY_CODEC_ALAW_56K = 3,
SKINNY_CODEC_ULAW_64K = 4,
SKINNY_CODEC_ULAW_56K = 5,
SKINNY_CODEC_G722_64K = 6,
SKINNY_CODEC_G722_56K = 7,
SKINNY_CODEC_G722_48K = 8,
SKINNY_CODEC_G723_1 = 9,
SKINNY_CODEC_G728 = 10,
SKINNY_CODEC_G729 = 11,
SKINNY_CODEC_G729A = 12,
SKINNY_CODEC_IS11172 = 13,
SKINNY_CODEC_IS13818 = 14,
SKINNY_CODEC_G729B = 15,
SKINNY_CODEC_G729AB = 16,
SKINNY_CODEC_GSM_FULL = 18,
SKINNY_CODEC_GSM_HALF = 19,
SKINNY_CODEC_GSM_EFULL = 20,
SKINNY_CODEC_WIDEBAND_256K = 25,
SKINNY_CODEC_DATA_64K = 32,
SKINNY_CODEC_DATA_56K = 33,
SKINNY_CODEC_G722_1_32K = 40,
SKINNY_CODEC_G722_1_24K = 41,
SKINNY_CODEC_GSM = 80,
SKINNY_CODEC_ACTIVEVOICE = 81,
SKINNY_CODEC_G726_32K = 82,
SKINNY_CODEC_G726_24K = 83,
SKINNY_CODEC_G726_16K = 84,
SKINNY_CODEC_G729B_BIS = 85,
SKINNY_CODEC_G729B_LOW = 86,
SKINNY_CODEC_H261 = 100,
SKINNY_CODEC_H263 = 101,
SKINNY_CODEC_VIDEO = 102,
SKINNY_CODEC_H264 = 103,
SKINNY_CODEC_T120 = 105,
SKINNY_CODEC_H224 = 106,
SKINNY_CODEC_RFC2833_DYNPAYLOAD = 257
} skinny_codecs;
char* skinny_codec2string(skinny_codecs skinnycodec);
/*****************************************************************************/
/* SKINNY MESSAGE DATA */
/*****************************************************************************/
@@ -145,6 +192,8 @@ struct PACKED capabilities_res_message {
struct station_capabilities caps[SWITCH_MAX_CODECS];
};
#define SERVER_REQ_MESSAGE 0x0012
/* AlarmMessage */
#define ALARM_MESSAGE 0x0020
struct PACKED alarm_message {
@@ -207,6 +256,147 @@ struct PACKED data_message {
#define DEVICE_TO_USER_DATA_RESPONSE_MESSAGE 0x002F
/* See struct PACKED data_message */
#define UPDATE_CAPABILITIES_MESSAGE 0x0030
#define MAX_CUSTOM_PICTURES 6
#define MAX_LAYOUT_WITH_SAME_SERVICE 5
#define MAX_SERVICE_TYPE 4
#define SKINNY_MAX_CAPABILITIES 18 /*!< max capabilities allowed in Cap response message */
#define SKINNY_MAX_VIDEO_CAPABILITIES 10
#define SKINNY_MAX_DATA_CAPABILITIES 5
#define MAX_LEVEL_PREFERENCE 4
/*!
* \brief Picture Format Structure
*/
typedef struct {
uint32_t custom_picture_format_width; /*!< Picture Width */
uint32_t custom_picture_format_height; /*!< Picture Height */
uint32_t custom_picture_format_pixelAspectRatio; /*!< Picture Pixel Aspect Ratio */
uint32_t custom_picture_format_pixelclockConversionCode; /*!< Picture Pixel Conversion Code */
uint32_t custom_picture_format_pixelclockDivisor; /*!< Picture Pixel Divisor */
} custom_picture_format_t;
/*!
* \brief Video Level Preference Structure
*/
typedef struct {
uint32_t transmitPreference; /*!< Transmit Preference */
uint32_t format; /*!< Format / Codec */
uint32_t maxBitRate; /*!< Maximum BitRate */
uint32_t minBitRate; /*!< Minimum BitRate */
uint32_t MPI; /*!< */
uint32_t serviceNumber; /*!< Service Number */
} levelPreference_t; /*!< Level Preference Structure */
/*!
* \brief Layout Config Structure (Update Capabilities Message Struct)
* \since 20080111
*/
typedef struct {
uint32_t layout; /*!< Layout \todo what is layout? */
} layoutConfig_t; /*!< Layout Config Structure */
/*!
* \brief Service Resource Structure
*/
typedef struct {
uint32_t layoutCount; /*!< Layout Count */
layoutConfig_t layout[MAX_LAYOUT_WITH_SAME_SERVICE]; /*!< Layout */
uint32_t serviceNum; /*!< Service Number */
uint32_t maxStreams; /*!< Maximum number of Streams */
uint32_t maxConferences; /*!< Maximum number of Conferences */
uint32_t activeConferenceOnRegistration; /*!< Active Conference On Registration */
} serviceResource_t;
/*!
* \brief Audio Capabilities Structure
*/
typedef struct {
skinny_codecs payload_capability; /*!< PayLoad Capability */
uint32_t maxFramesPerPacket; /*!< Maximum Number of Frames per IP Packet */
uint32_t unknown[2]; /*!< this are related to G.723 */
} audioCap_t;
/*!
* \brief Video Capabilities Structure
*/
typedef struct {
skinny_codecs payload_capability; /*!< PayLoad Capability */
uint32_t transmitOreceive; /*!< Transmit of Receive */
uint32_t levelPreferenceCount; /*!< Level of Preference Count */
levelPreference_t levelPreference[MAX_LEVEL_PREFERENCE]; /*!< Level Preference */
// uint32_t codec_options[2]; /*!< Codec Options */
union {
struct {
uint32_t unknown1;
uint32_t unknown2;
} h263;
struct {
uint32_t profile; /*!< H264 profile */
uint32_t level; /*!< H264 level */
} h264;
} codec_options;
/**
* Codec options contains data specific for every codec
*
* Here is a list of known parameters per codec
// H.261
uint32_t temporalSpatialTradeOffCapability;
uint32_t stillImageTransmission;
// H.263
uint32_t h263_capability_bitfield;
uint32_t annexNandWFutureUse;
// Video
uint32_t modelNumber;
uint32_t bandwidth;
*/
} videoCap_t; /*!< Video Capabilities Structure */
/*!
* \brief Data Capabilities Structure
*/
typedef struct {
uint32_t payload_capability; /*!< Payload Capability */
uint32_t transmitOrReceive; /*!< Transmit or Receive */
uint32_t protocolDependentData; /*!< Protocol Dependent Data */
uint32_t maxBitRate; /*!< Maximum BitRate */
} dataCap_t; /*!< Data Capabilities Structure */
struct PACKED update_capabilities_message {
uint32_t audio_cap_count; /*!< Audio Capability Count */
uint32_t videoCapCount; /*!< Video Capability Count */
uint32_t dataCapCount; /*!< Data Capability Count */
uint32_t RTPPayloadFormat; /*!< RTP Payload Format */
uint32_t custom_picture_formatCount; /*!< Custom Picture Format Count */
custom_picture_format_t custom_picture_format[MAX_CUSTOM_PICTURES]; /*!< Custom Picture Format */
uint32_t activeStreamsOnRegistration; /*!< Active Streams on Registration */
uint32_t maxBW; /*!< Max BW ?? */
uint32_t serviceResourceCount; /*!< Service Resource Count */
serviceResource_t serviceResource[MAX_SERVICE_TYPE]; /*!< Service Resource */
audioCap_t audioCaps[SKINNY_MAX_CAPABILITIES]; /*!< Audio Capabilities */
videoCap_t videoCaps[SKINNY_MAX_VIDEO_CAPABILITIES]; /*!< Video Capabilities */
dataCap_t dataCaps[SKINNY_MAX_DATA_CAPABILITIES]; /*!< Data Capabilities */
uint32_t unknown; /*!< Unknown */
};
/* ServiceUrlStatReqMessage */
#define SERVICE_URL_STAT_REQ_MESSAGE 0x0033
struct PACKED service_url_stat_req_message {
@@ -442,6 +632,23 @@ struct PACKED register_reject_message {
char error[33];
};
#define SERVER_RESPONSE_MESSAGE 0x009E
#define ServerMaxNameSize 48
#define StationMaxServers 5
/*!
* \brief Station Identifier Structure
*/
typedef struct {
char serverName[ServerMaxNameSize]; /*!< Server Name */
} ServerIdentifier;
struct PACKED server_response_message {
ServerIdentifier server[StationMaxServers]; /*!< Server Identifier */
uint32_t serverListenPort[StationMaxServers]; /*!< Server is Listening on Port */
uint32_t serverIpAddr[StationMaxServers]; /*!< Server IP Port */
}; /*!< Server Result Message Structure */
/* ResetMessage */
#define RESET_MESSAGE 0x009F
struct PACKED reset_message {
@@ -670,6 +877,7 @@ union skinny_data {
/* no data for CAPABILITIES_REQ_MESSAGE */
struct register_reject_message reg_rej;
struct reset_message reset;
struct server_response_message serv_res_mess;
/* no data for KEEP_ALIVE_ACK_MESSAGE */
struct open_receive_channel_message open_receive_channel;
struct close_receive_channel_message close_receive_channel;
@@ -690,6 +898,7 @@ union skinny_data {
/* see field "extended_data" for USER_TO_DEVICE_DATA_VERSION1_MESSAGE */
struct dialed_phone_book_ack_message dialed_phone_book_ack;
struct update_capabilities_message upd_cap;
struct data_message data;
struct extended_data_message extended_data;
@@ -702,7 +911,7 @@ union skinny_data {
#endif
/*
* header is length+reserved
* header is length+version
* body is type+data
* length is length of body
*/
@@ -719,47 +928,7 @@ struct PACKED skinny_message {
typedef struct skinny_message skinny_message_t;
/*****************************************************************************/
/* SKINNY TYPES */
/*****************************************************************************/
enum skinny_codecs {
SKINNY_CODEC_ALAW_64K = 2,
SKINNY_CODEC_ALAW_56K = 3,
SKINNY_CODEC_ULAW_64K = 4,
SKINNY_CODEC_ULAW_56K = 5,
SKINNY_CODEC_G722_64K = 6,
SKINNY_CODEC_G722_56K = 7,
SKINNY_CODEC_G722_48K = 8,
SKINNY_CODEC_G723_1 = 9,
SKINNY_CODEC_G728 = 10,
SKINNY_CODEC_G729 = 11,
SKINNY_CODEC_G729A = 12,
SKINNY_CODEC_IS11172 = 13,
SKINNY_CODEC_IS13818 = 14,
SKINNY_CODEC_G729B = 15,
SKINNY_CODEC_G729AB = 16,
SKINNY_CODEC_GSM_FULL = 18,
SKINNY_CODEC_GSM_HALF = 19,
SKINNY_CODEC_GSM_EFULL = 20,
SKINNY_CODEC_WIDEBAND_256K = 25,
SKINNY_CODEC_DATA_64K = 32,
SKINNY_CODEC_DATA_56K = 33,
SKINNY_CODEC_GSM = 80,
SKINNY_CODEC_ACTIVEVOICE = 81,
SKINNY_CODEC_G726_32K = 82,
SKINNY_CODEC_G726_24K = 83,
SKINNY_CODEC_G726_16K = 84,
SKINNY_CODEC_G729B_BIS = 85,
SKINNY_CODEC_G729B_LOW = 86,
SKINNY_CODEC_H261 = 100,
SKINNY_CODEC_H263 = 101,
SKINNY_CODEC_VIDEO = 102,
SKINNY_CODEC_T120 = 105,
SKINNY_CODEC_H224 = 106,
SKINNY_CODEC_RFC2833_DYNPAYLOAD = 257
};
char* skinny_codec2string(enum skinny_codecs skinnycodec);
/*****************************************************************************/
/* SKINNY FUNCTIONS */
@@ -851,6 +1020,11 @@ switch_status_t perform_send_set_speaker_mode(listener_t *listener,
uint32_t mode);
#define send_set_speaker_mode(listener, ...) perform_send_set_speaker_mode(listener, __FILE__, __SWITCH_FUNC__, __LINE__, __VA_ARGS__)
switch_status_t perform_send_srvreq_response(listener_t *listener,
const char *file, const char *func, int line,
char *ip, uint32_t port);
#define send_srvreq_response(listener, ...) perform_send_srvreq_response(listener, __FILE__, __SWITCH_FUNC__, __LINE__, __VA_ARGS__)
switch_status_t perform_send_start_media_transmission(listener_t *listener,
const char *file, const char *func, int line,
uint32_t conference_id,
+78 -1
View File
@@ -2184,6 +2184,79 @@ switch_status_t skinny_handle_accessory_status_message(listener_t *listener, ski
return SWITCH_STATUS_SUCCESS;
}
switch_status_t skinny_handle_updatecapabilities(listener_t *listener, skinny_message_t *request)
{
char *sql;
skinny_profile_t *profile;
uint32_t i = 0;
uint32_t n = 0;
char *codec_order[SWITCH_MAX_CODECS];
char *codec_string;
size_t string_len, string_pos, pos;
switch_assert(listener->profile);
switch_assert(listener->device_name);
profile = listener->profile;
skinny_check_data_length(request, sizeof(request->data.upd_cap.audio_cap_count));
n = request->data.upd_cap.audio_cap_count;
if (n > SWITCH_MAX_CODECS) {
n = SWITCH_MAX_CODECS;
}
string_len = -1;
skinny_check_data_length(request, sizeof(request->data.upd_cap.audio_cap_count) + n * sizeof(request->data.upd_cap.audioCaps[0]));
for (i = 0; i < n; i++) {
char *codec = skinny_codec2string(request->data.upd_cap.audioCaps[i].payload_capability);
codec_order[i] = codec;
string_len += strlen(codec)+1;
}
i = 0;
pos = 0;
codec_string = switch_core_alloc(listener->pool, string_len+1);
for (string_pos = 0; string_pos < string_len; string_pos++) {
char *codec = codec_order[i];
switch_assert(i < n);
if(pos == strlen(codec)) {
codec_string[string_pos] = ',';
i++;
pos = 0;
} else {
codec_string[string_pos] = codec[pos++];
}
}
codec_string[string_len] = '\0';
if ((sql = switch_mprintf(
"UPDATE skinny_devices SET codec_string='%s' WHERE name='%s'",
codec_string,
listener->device_name
))) {
skinny_execute_sql(profile, sql, profile->sql_mutex);
switch_safe_free(sql);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
"Codecs %s supported.\n", codec_string);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t skinny_handle_server_req_message(listener_t *listener, skinny_message_t *request)
{
skinny_profile_t *profile;
profile = listener->profile;
skinny_log_l(listener, SWITCH_LOG_INFO, "Received Server Request Message (length=%d).\n", request->length);
send_srvreq_response(listener, profile->ip, profile->port);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t skinny_handle_xml_alarm(listener_t *listener, skinny_message_t *request)
{
switch_event_t *event = NULL;
@@ -2209,7 +2282,7 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re
skinny_log_l(listener, SWITCH_LOG_DEBUG, "Received %s (type=%x,length=%d).\n",
skinny_message_type2str(request->type), request->type, request->length);
}
if(zstr(listener->device_name) && request->type != REGISTER_MESSAGE && request->type != ALARM_MESSAGE && request->type != XML_ALARM_MESSAGE) {
if(zstr(listener->device_name) && request->type != REGISTER_MESSAGE && request->type != ALARM_MESSAGE && request->type != XML_ALARM_MESSAGE && request->type != KEEP_ALIVE_MESSAGE) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Device should send a register message first. Received %s (type=%x,length=%d).\n", skinny_message_type2str(request->type), request->type, request->length);
return SWITCH_STATUS_FALSE;
@@ -2281,6 +2354,10 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re
return skinny_handle_accessory_status_message(listener, request);
case XML_ALARM_MESSAGE:
return skinny_handle_xml_alarm(listener, request);
case UPDATE_CAPABILITIES_MESSAGE:
return skinny_handle_updatecapabilities(listener, request);
case SERVER_REQ_MESSAGE:
return skinny_handle_server_req_message(listener, request);
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Unhandled %s (type=%x,length=%d).\n", skinny_message_type2str(request->type), request->type, request->length);
+54 -10
View File
@@ -61,6 +61,7 @@ struct skinny_table SKINNY_MESSAGE_TYPES[] = {
{REGISTER_AVAILABLE_LINES_MESSAGE, "RegisterAvailableLinesMessage"},
{DEVICE_TO_USER_DATA_MESSAGE, "DeviceToUserDataMessage"},
{DEVICE_TO_USER_DATA_RESPONSE_MESSAGE, "DeviceToUserDataResponseMessage"},
{UPDATE_CAPABILITIES_MESSAGE, "DeviceUpdateCapabilities"},
{SERVICE_URL_STAT_REQ_MESSAGE, "ServiceUrlStatReqMessage"},
{FEATURE_STAT_REQ_MESSAGE, "FeatureStatReqMessage"},
{DEVICE_TO_USER_DATA_VERSION1_MESSAGE, "DeviceToUserDataVersion1Message"},
@@ -84,7 +85,9 @@ struct skinny_table SKINNY_MESSAGE_TYPES[] = {
{BUTTON_TEMPLATE_RES_MESSAGE, "ButtonTemplateResMessage"},
{VERSION_MESSAGE, "VersionMessage"},
{CAPABILITIES_REQ_MESSAGE, "CapabilitiesReqMessage"},
{SERVER_REQ_MESSAGE, "Server Request Message"},
{REGISTER_REJECT_MESSAGE, "RegisterRejectMessage"},
{SERVER_RESPONSE_MESSAGE, "ServerResponseMessage"},
{RESET_MESSAGE, "ResetMessage"},
{KEEP_ALIVE_ACK_MESSAGE, "KeepAliveAckMessage"},
{OPEN_RECEIVE_CHANNEL_MESSAGE, "OpenReceiveChannelMessage"},
@@ -115,18 +118,59 @@ SKINNY_DECLARE_STR2ID(skinny_str2message_type, SKINNY_MESSAGE_TYPES, -1)
{1, "Cisco 30 SP+"},
{2, "Cisco 12 SP+"},
{3, "Cisco 12 SP"},
{4, "Cisco 12"},
{4, "Cisco 12 S"},
{5, "Cisco 30 VIP"},
{6, "Cisco IP Phone 7910"},
{7, "Cisco IP Phone 7960"},
{8, "Cisco IP Phone 7940"},
{9, "Cisco IP Phone 7935"},
{6, "Cisco 7910"},
{7, "Cisco 7960"},
{8, "Cisco 7940"},
{9, "Cisco 7935"},
{10, "Cisco VGC Phone"},
{11, "Cisco VGC Virtual Phone"},
{12, "Cisco ATA 186"},
{365, "Cisco IP Phone CP-7921G"},
{404, "Cisco IP Phone CP-7962G"},
{436, "Cisco IP Phone CP-7965G"},
{30018, "Cisco IP Phone CP-7961G"},
{30019, "Cisco IP Phone 7936"},
{30, "Cisco Analog Access"},
{40, "Cisco Digital Access"},
{42, "Cisco Digital Access+"},
{43, "Cisco Digital Access WS-X6608"},
{47, "Cisco Analog Access WS-X6624"},
{51, "Cisco Conference Bridge WS-X6608"},
{61, "Cisco H.323 Phone"},
{100, "Cisco Load Simulator"},
{111, "Cisco Media Termination Point Hardware"},
{115, "Cisco 7941"},
{115, "Cisco CP-7941G"},
{119, "Cisco 7971"},
{120, "Cisco MGCP Station"},
{121, "Cisco MGCP Trunk"},
{124, "Cisco 7914 14-Button Line Expansion Module"},
{302, "Cisco 7985"},
{307, "Cisco 7911"},
{308, "Cisco 7961G-GE"},
{309, "Cisco 7941G-GE"},
{335, "Cisco Motorola CN622"},
{348, "Cisco 7931"},
{358, "Cisco Unified Personal Communicator"},
{365, "Cisco 7921"},
{369, "Cisco 7906"},
{375, "Cisco TelePresence"},
{404, "Cisco 7962"},
{412, "Cisco 3951"},
{431, "Cisco 7937"},
{434, "Cisco 7942"},
{435, "Cisco 7945"},
{436, "Cisco 7965"},
{437, "Cisco 7975"},
{446, "Cisco 3911"},
{20000, "Cisco 7905"},
{30002, "Cisco 7920"},
{30006, "Cisco 7970"},
{30007, "Cisco 7912"},
{30008, "Cisco 7902"},
{30018, "Cisco 7961"},
{30019, "Cisco 7936"},
{30027, "Cisco Analog Phone"},
{30028, "Cisco ISDN BRI Phone"},
{30032, "Cisco SCCP gateway virtual phone"},
{30035, "Cisco IP-STE"},
{0, NULL}
};
SKINNY_DECLARE_ID2STR(skinny_device_type2str, SKINNY_DEVICE_TYPES, "UnknownDeviceType")
+2 -2
View File
@@ -87,12 +87,12 @@ if (my_matches) {\
}
extern struct skinny_table SKINNY_MESSAGE_TYPES[72];
extern struct skinny_table SKINNY_MESSAGE_TYPES[75];
const char *skinny_message_type2str(uint32_t id);
uint32_t skinny_str2message_type(const char *str);
#define SKINNY_PUSH_MESSAGE_TYPES SKINNY_DECLARE_PUSH_MATCH(SKINNY_MESSAGE_TYPES)
extern struct skinny_table SKINNY_DEVICE_TYPES[16];
extern struct skinny_table SKINNY_DEVICE_TYPES[75];
const char *skinny_device_type2str(uint32_t id);
uint32_t skinny_str2device_type(const char *str);
#define SKINNY_PUSH_DEVICE_TYPES SKINNY_DECLARE_PUSH_MATCH(SKINNY_DEVICE_TYPES)
+47 -8
View File
@@ -126,6 +126,7 @@ typedef struct switch_rtp_engine_s {
uint32_t max_missed_packets;
uint32_t max_missed_hold_packets;
uint32_t ssrc;
uint32_t remote_ssrc;
switch_port_t remote_rtcp_port;
switch_rtp_bug_flag_t rtp_bugs;
@@ -1985,6 +1986,8 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
generate_local_fingerprint(smh, type);
switch_channel_set_flag(smh->session->channel, CF_DTLS);
} else if (!engine->remote_ssrc && !strcasecmp(attr->a_name, "ssrc") && attr->a_value) {
engine->remote_ssrc = (uint32_t) atol(attr->a_value);
#ifdef RTCP_MUX
} else if (!strcasecmp(attr->a_name, "rtcp-mux")) {
engine->rtcp_mux = SWITCH_TRUE;
@@ -2294,7 +2297,6 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
codec_array = smh->codecs;
total_codecs = smh->mparams->num_codecs;
if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
return 0;
}
@@ -2459,9 +2461,12 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
got_webrtc++;
switch_core_session_set_ice(session);
}
if (m->m_proto_name && !strcasecmp(m->m_proto_name, "UDP/TLS/RTP/SAVPF")) {
switch_channel_set_flag(session->channel, CF_WEBRTC_MOZ);
printf("PRICK FACE 1\n");
} else {
printf("PRICK FACE 2 [%s]\n", m->m_proto_name);
}
if (m->m_proto == sdp_proto_srtp || m->m_proto == sdp_proto_extended_srtp) {
@@ -3790,7 +3795,8 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread started\n", switch_channel_get_name(session->channel));
switch_core_session_refresh_video(session);
switch_channel_set_flag(channel, CF_VIDEO_ECHO);
while (switch_channel_up_nosig(channel)) {
if (switch_channel_test_flag(channel, CF_VIDEO_PASSIVE)) {
@@ -3812,7 +3818,6 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi
status = switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
if (!SWITCH_READ_ACCEPTABLE(status)) {
switch_cond_next();
continue;
@@ -3828,7 +3833,9 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi
continue;
}
switch_core_session_write_video_frame(session, read_frame, SWITCH_IO_FLAG_NONE, 0);
if (switch_channel_test_flag(channel, CF_VIDEO_ECHO)) {
switch_core_session_write_video_frame(session, read_frame, SWITCH_IO_FLAG_NONE, 0);
}
}
@@ -4092,6 +4099,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
switch_rtp_set_ssrc(a_engine->rtp_session, a_engine->ssrc);
}
if (a_engine->remote_ssrc) {
switch_rtp_set_remote_ssrc(a_engine->rtp_session, a_engine->remote_ssrc);
}
switch_channel_set_flag(session->channel, CF_FS_RTP);
@@ -4552,6 +4562,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
switch_rtp_set_ssrc(v_engine->rtp_session, v_engine->ssrc);
}
if (v_engine->remote_ssrc) {
switch_rtp_set_remote_ssrc(v_engine->rtp_session, v_engine->remote_ssrc);
}
if (v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].ready) {
gen_ice(session, SWITCH_MEDIA_TYPE_VIDEO, NULL, 0);
@@ -5125,7 +5139,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
switch_rtp_engine_t *a_engine, *v_engine;
switch_media_handle_t *smh;
ice_t *ice_out;
int vp8 = 0;
switch_assert(session);
@@ -5629,6 +5643,10 @@ 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;
}
rate = v_engine->codec_params.rm_rate;
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\n",
@@ -5694,6 +5712,10 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
channels = get_channels(imp);
if (!strcasecmp(imp->iananame, "VP8")) {
vp8 = ianacode;
}
if (channels > 1) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\n", ianacode, imp->iananame,
imp->samples_per_second, channels);
@@ -5733,7 +5755,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
}
if (smh->mparams->rtcp_audio_interval_msec) {
if (smh->mparams->rtcp_video_interval_msec) {
if (v_engine->rtcp_mux > 0) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp-mux\n");
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\n", v_port, family, ip);
@@ -5751,7 +5773,9 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
uint32_t c2 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 2);
uint32_t c3 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 1);
uint32_t c4 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 2);
const char *vbw;
int bw = 256;
tmp1[10] = '\0';
tmp2[10] = '\0';
switch_stun_random_string(tmp1, 10, "0123456789");
@@ -5760,6 +5784,21 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
ice_out = &v_engine->ice_out;
if ((vbw = switch_channel_get_variable(smh->session->channel, "rtp_video_max_bandwidth"))) {
int v = atoi(vbw);
bw = v;
}
if (bw > 0) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "b=AS:%d\n", bw);
}
if (vp8) {
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf),
"a=rtcp-fb:%d ccm fir\n", vp8);
}
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u cname:%s\n", v_engine->ssrc, smh->cname);
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u msid:%s v0\n", v_engine->ssrc, smh->msid);
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u mslabel:%s\n", v_engine->ssrc, smh->msid);
+4
View File
@@ -2567,6 +2567,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flag
*flags = application_interface->flags;
}
if (!switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA) && (switch_channel_test_flag(session->channel, CF_VIDEO))) {
switch_core_session_refresh_video(session);
}
if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) && !switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA)) {
switch_ivr_media(session->uuid_str, SMF_NONE);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Application %s Requires media on channel %s!\n",
+246 -45
View File
@@ -34,6 +34,8 @@
//#define RTP_DEBUG_WRITE_DELTA
//#define DEBUG_MISSED_SEQ
#define FIR_COUNTDOWN 100
#include <switch.h>
#ifndef _MSC_VER
#include <switch_private.h>
@@ -116,7 +118,6 @@ typedef struct {
uint8_t r3;
} rtcp_fir_t;
#ifdef _MSC_VER
#pragma pack(push, r1, 1)
#endif
@@ -264,6 +265,13 @@ static int dtls_state_dummy(switch_rtp_t *rtp_session, switch_dtls_t *dtls);
dtls_state_handler_t dtls_states[DS_INVALID] = {dtls_state_handshake, dtls_state_setup, dtls_state_ready, dtls_state_dummy};
typedef struct ts_normalize_s {
uint32_t last_ssrc;
uint32_t last_frame;
uint32_t ts;
uint32_t delta;
uint8_t m;
} ts_normalize_t;
struct switch_rtp {
/*
@@ -281,6 +289,8 @@ struct switch_rtp {
rtcp_msg_t rtcp_send_msg;
rtcp_ext_msg_t rtcp_ext_send_msg;
uint8_t fir_seq;
uint16_t fir_countdown;
ts_normalize_t ts_norm;
switch_sockaddr_t *remote_addr, *rtcp_remote_addr;
rtp_msg_t recv_msg;
rtcp_msg_t rtcp_recv_msg;
@@ -307,6 +317,7 @@ struct switch_rtp {
uint16_t seq;
uint32_t ssrc;
uint32_t remote_ssrc;
int8_t sending_dtmf;
uint8_t need_mark;
switch_payload_t payload;
@@ -698,10 +709,10 @@ 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 (PUNT!)\n");
status = SWITCH_STATUS_GENERR;
goto end;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "No stun for a long time!\n");
rtp_session->last_stun = switch_micro_time_now();
//status = SWITCH_STATUS_GENERR;
//goto end;
}
}
@@ -743,7 +754,7 @@ static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice)
ice->sending = 3;
end:
// end:
READ_DEC(rtp_session);
return status;
@@ -1329,20 +1340,31 @@ static void send_fir(switch_rtp_t *rtp_session)
return;
}
if (rtp_session->remote_ssrc == 0) {
rtp_session->remote_ssrc = rtp_session->stats.rtcp.peer_ssrc;
}
if (rtp_session->remote_ssrc == 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG, "Peer ssrc not known yet for FIR\n");
return;
}
if (rtp_session->rtcp_sock_output && rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP]) {
rtcp_fir_t *fir = (rtcp_fir_t *) rtp_session->rtcp_ext_send_msg.body;
switch_size_t rtcp_bytes;
rtp_session->rtcp_ext_send_msg.header.version = 2;
rtp_session->rtcp_ext_send_msg.header.p = 0;
rtp_session->rtcp_ext_send_msg.header.fmt = 4;
rtp_session->rtcp_ext_send_msg.header.pt = 206;
rtp_session->rtcp_ext_send_msg.header.send_ssrc = htonl(rtp_session->ssrc);
rtp_session->rtcp_ext_send_msg.header.recv_ssrc = htonl(rtp_session->stats.rtcp.peer_ssrc);
rtp_session->rtcp_ext_send_msg.header.recv_ssrc = 0;//htonl(rtp_session->stats.rtcp.peer_ssrc);
fir->ssrc = htonl(rtp_session->stats.rtcp.peer_ssrc);
fir->seq = (uint8_t) htonl(rtp_session->fir_seq++);
//fir->ssrc = htonl(rtp_session->stats.rtcp.peer_ssrc);
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);
@@ -1409,6 +1431,92 @@ static void send_fir(switch_rtp_t *rtp_session)
return;
}
#if 0
static void send_pli(switch_rtp_t *rtp_session)
{
if (!rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && rtp_session->ice.ice_user) {
return;
}
if (rtp_session->rtcp_sock_output && rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP]) {
switch_size_t rtcp_bytes;
rtp_session->rtcp_ext_send_msg.header.version = 2;
rtp_session->rtcp_ext_send_msg.header.p = 0;
rtp_session->rtcp_ext_send_msg.header.fmt = 1;
rtp_session->rtcp_ext_send_msg.header.pt = 206;
rtp_session->rtcp_ext_send_msg.header.send_ssrc = htonl(rtp_session->ssrc);
rtp_session->rtcp_ext_send_msg.header.recv_ssrc = 0;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG1, "Sending RTCP PLI\n");
rtcp_bytes = sizeof(switch_rtcp_ext_hdr_t);
rtp_session->rtcp_ext_send_msg.header.length = htons((u_short)(rtcp_bytes / 4) - 1);
#ifdef ENABLE_SRTP
if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND]) {
int sbytes = (int) rtcp_bytes;
int stat = srtp_protect_rtcp(rtp_session->send_ctx[rtp_session->srtp_idx_rtcp], &rtp_session->rtcp_ext_send_msg.header, &sbytes);
if (stat) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error: SRTP RTCP protection failed with code %d\n", stat);
goto end;
} else {
rtcp_bytes = sbytes;
}
}
#endif
#ifdef ENABLE_ZRTP
/* ZRTP Send */
if (zrtp_on && !rtp_session->flags[SWITCH_RTP_FLAG_PROXY_MEDIA]) {
unsigned int sbytes = (int) rtcp_bytes;
zrtp_status_t stat = zrtp_status_fail;
stat = zrtp_process_rtcp(rtp_session->zrtp_stream, (void *) &rtp_session->rtcp_ext_send_msg, &sbytes);
switch (stat) {
case zrtp_status_ok:
break;
case zrtp_status_drop:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection drop with code %d\n", stat);
goto end;
break;
case zrtp_status_fail:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection fail with code %d\n", stat);
break;
default:
break;
}
rtcp_bytes = sbytes;
}
#endif
#ifdef DEBUG_EXTRA
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_CRIT, "%s SEND %s RTCP %ld\n",
switch_core_session_get_name(rtp_session->session),
rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] ? "video" : "audio", rtcp_bytes);
#endif
if (switch_socket_sendto(rtp_session->rtcp_sock_output, rtp_session->rtcp_remote_addr, 0, (void *)&rtp_session->rtcp_ext_send_msg, &rtcp_bytes ) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG,"RTCP packet not written\n");
} else {
rtp_session->stats.inbound.period_packet_count = 0;
}
}
end:
return;
}
#endif
static int check_rtcp_and_ice(switch_rtp_t *rtp_session)
{
int ret = 0;
@@ -1442,10 +1550,6 @@ static int check_rtcp_and_ice(switch_rtp_t *rtp_session)
rtcp_ok = 0;
}
//if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
// rtcp_ok = 0;
//}
if (rtp_session->rtcp_sock_output && rtcp_ok && rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP] && !rtp_session->flags[SWITCH_RTP_FLAG_RTCP_PASSTHRU]) {
struct switch_rtcp_senderinfo *sr = (struct switch_rtcp_senderinfo*) rtp_session->rtcp_send_msg.body;
const char* str_cname=NULL;
@@ -2123,6 +2227,10 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_address(switch_rtp_t *rtp_
status = enable_remote_rtcp_socket(rtp_session, err);
}
if (rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP] && rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) {
rtp_session->rtcp_remote_addr = rtp_session->remote_addr;
}
switch_mutex_unlock(rtp_session->write_mutex);
return status;
@@ -2224,7 +2332,7 @@ static int dtls_state_ready(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
if (dtls->new_state) {
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
switch_core_session_t *other_session;
send_fir(rtp_session);
rtp_session->fir_countdown = FIR_COUNTDOWN;
if (rtp_session->session && switch_core_session_get_partner(rtp_session->session, &other_session) == SWITCH_STATUS_SUCCESS) {
switch_core_session_refresh_video(other_session);
@@ -2682,6 +2790,13 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_ssrc(switch_rtp_t *rtp_session, u
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_ssrc(switch_rtp_t *rtp_session, uint32_t ssrc)
{
rtp_session->remote_ssrc = ssrc;
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session,
switch_payload_t payload,
uint32_t samples_per_interval,
@@ -2781,6 +2896,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session
switch_rtp_clear_flag(rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
}
if (channel) {
switch_channel_set_private(channel, "__rtcp_audio_rtp_session", rtp_session);
}
@@ -3221,7 +3337,10 @@ SWITCH_DECLARE(void) switch_rtp_flush(switch_rtp_t *rtp_session)
SWITCH_DECLARE(void) switch_rtp_video_refresh(switch_rtp_t *rtp_session)
{
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && rtp_session->ice.ice_user) {
send_fir(rtp_session);
if (!rtp_session->fir_countdown) {
//send_fir(rtp_session);
rtp_session->fir_countdown = FIR_COUNTDOWN;
}
}
}
@@ -3827,6 +3946,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
uint32_t ts = 0;
unsigned char *b = NULL;
int sync = 0;
switch_time_t now;
switch_assert(bytes);
more:
@@ -3896,15 +4016,14 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
}
}
if (status == SWITCH_STATUS_SUCCESS && *bytes) {
if (rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) {
*flags &= ~SFF_RTCP;
if (rtp_session->recv_msg.header.pt != rtp_session->rpayload && (!rtp_session->recv_te ||
rtp_session->recv_msg.header.pt != rtp_session->recv_te) &&
if (rtp_session->recv_msg.header.pt != rtp_session->rpayload &&
(!rtp_session->recv_te || rtp_session->recv_msg.header.pt != rtp_session->recv_te) &&
(!rtp_session->cng_pt || rtp_session->recv_msg.header.pt != rtp_session->cng_pt) &&
rtp_session->rtcp_recv_msg_p->header.version == 2 && rtp_session->rtcp_recv_msg_p->header.type > 199 &&
rtp_session->rtcp_recv_msg_p->header.type < 208) { //rtcp muxed
rtp_session->rtcp_recv_msg_p->header.version == 2 &&
rtp_session->rtcp_recv_msg_p->header.type > 199 && rtp_session->rtcp_recv_msg_p->header.type < 208) { //rtcp muxed
*flags |= SFF_RTCP;
return SWITCH_STATUS_SUCCESS;
}
@@ -3952,11 +4071,13 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
udptl:
ts = ntohl(rtp_session->recv_msg.header.ts);
ts = 0;
rtp_session->recv_msg.ebody = NULL;
now = switch_micro_time_now();
if (*bytes) {
uint16_t seq = ntohs((uint16_t) rtp_session->recv_msg.header.seq);
ts = ntohl(rtp_session->recv_msg.header.ts);
if (!rtp_session->flags[SWITCH_RTP_FLAG_PROXY_MEDIA] && !rtp_session->flags[SWITCH_RTP_FLAG_UDPTL] &&
rtp_session->recv_msg.header.version == 2 && rtp_session->recv_msg.header.x) { /* header extensions */
@@ -3981,40 +4102,47 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
if (num_missed == 1) { /* We missed one packet */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missed one RTP frame with sequence [%d]%s. Time since last read [%ld]\n",
rtp_session->last_seq+1, (flushed_packets_diff == 1) ? " (flushed by FS)" : " (missed)",
rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
rtp_session->last_read_time ? now-rtp_session->last_read_time : 0);
} else { /* We missed multiple packets */
if (flushed_packets_diff == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Missed %ld RTP frames from sequence [%d] to [%d] (missed). Time since last read [%ld]\n",
num_missed, rtp_session->last_seq+1, seq-1,
rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
rtp_session->last_read_time ? now-rtp_session->last_read_time : 0);
} else if (flushed_packets_diff == num_missed) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Missed %ld RTP frames from sequence [%d] to [%d] (flushed by FS). Time since last read [%ld]\n",
num_missed, rtp_session->last_seq+1, seq-1,
rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
rtp_session->last_read_time ? now-rtp_session->last_read_time : 0);
} else if (num_missed > flushed_packets_diff) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Missed %ld RTP frames from sequence [%d] to [%d] (%ld packets flushed by FS, %ld packets missed)."
" Time since last read [%ld]\n",
num_missed, rtp_session->last_seq+1, seq-1,
flushed_packets_diff, num_missed-flushed_packets_diff,
rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
rtp_session->last_read_time ? now-rtp_session->last_read_time : 0);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Missed %ld RTP frames from sequence [%d] to [%d] (%ld packets flushed by FS). Time since last read [%ld]\n",
num_missed, rtp_session->last_seq+1, seq-1,
flushed_packets_diff, rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
flushed_packets_diff, rtp_session->last_read_time ? now-rtp_session->last_read_time : 0);
}
}
}
#endif
rtp_session->last_seq = seq;
}
rtp_session->last_flush_packet_count = rtp_session->stats.inbound.flush_packet_count;
rtp_session->last_read_time = switch_micro_time_now();
rtp_session->last_flush_packet_count = rtp_session->stats.inbound.flush_packet_count;
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && now - rtp_session->last_read_time > 500000) {
switch_rtp_video_refresh(rtp_session);
}
rtp_session->last_read_time = now;
}
if (!rtp_session->flags[SWITCH_RTP_FLAG_PROXY_MEDIA] && !rtp_session->flags[SWITCH_RTP_FLAG_UDPTL] && !rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] &&
*bytes && (!rtp_session->recv_te || rtp_session->recv_msg.header.pt != rtp_session->recv_te) &&
@@ -4121,7 +4249,17 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
}
rtp_session->last_read_ts = ts;
if (*bytes && rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
unsigned int diff = ts - rtp_session->last_read_ts;
if (abs(diff) > 10000) {
switch_rtp_video_refresh(rtp_session);
}
}
if (ts) {
rtp_session->last_read_ts = ts;
}
if (rtp_session->flags[SWITCH_RTP_FLAG_BYTESWAP] && rtp_session->recv_msg.header.pt == rtp_session->rpayload) {
switch_swap_linear((int16_t *)RTP_BODY(rtp_session), (int) *bytes - rtp_header_len);
@@ -4251,16 +4389,13 @@ static switch_status_t read_rtcp_packet(switch_rtp_t *rtp_session, switch_size_t
if (rtp_session->rtcp_dtls) {
char *b = (char *) &rtp_session->rtcp_recv_msg;
//printf("RECV2 %d %ld\n", *b, *bytes);
if (*b == 0 || *b == 1) {
if (rtp_session->rtcp_ice.ice_user) {
handle_ice(rtp_session, &rtp_session->rtcp_ice, (void *) &rtp_session->rtcp_recv_msg, *bytes);
}
*bytes = 0;
}
if (*bytes && (*b >= 20) && (*b <= 64)) {
rtp_session->rtcp_dtls->bytes = *bytes;
rtp_session->rtcp_dtls->data = (void *) &rtp_session->rtcp_recv_msg;
@@ -4474,14 +4609,15 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
pt = 20000;
}
if ((rtp_session->ice.ice_user && rtp_session->flags[SWITCH_RTP_FLAG_VIDEO])) {
pt = 10000;
}
if ((io_flags & SWITCH_IO_FLAG_NOBLOCK)) {
pt = 0;
}
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
pt = 100000;
}
poll_status = switch_poll(rtp_session->read_pollfd, 1, &fdr, pt);
if (rtp_session->dtmf_data.out_digit_dur > 0) {
@@ -4499,6 +4635,22 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
ret = -1;
goto end;
}
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
//switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_CRIT, "Read bytes (%i) %ld\n", status, bytes);
if (bytes == 0) {
if (check_rtcp_and_ice(rtp_session) == -1) {
ret = -1;
goto end;
}
// This is dumb
switch_rtp_video_refresh(rtp_session);
goto rtcp;
}
}
if ((*flags & SFF_PROXY_PACKET)) {
ret = (int) bytes;
goto end;
@@ -4509,8 +4661,8 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
has_rtcp = 1;
goto rtcp;
}
//switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG, "Read bytes (%i) %ld\n", status, bytes);
}
poll_loop = 0;
} else {
@@ -4539,9 +4691,11 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
ret = -1;
goto end;
}
} else if ((!(io_flags & SWITCH_IO_FLAG_NOBLOCK)) &&
(rtp_session->dtmf_data.out_digit_dur == 0)) {
goto recvfrom;
}
if ((!(io_flags & SWITCH_IO_FLAG_NOBLOCK)) &&
(rtp_session->dtmf_data.out_digit_dur == 0)) {
return_cng_frame();
}
}
@@ -4572,7 +4726,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
if (rtcp_status == SWITCH_STATUS_SUCCESS) {
switch_rtp_reset_media_timer(rtp_session);
if (rtp_session->flags[SWITCH_RTP_FLAG_RTCP_PASSTHRU] || rtp_session->rtcp_recv_msg_p->header.type == 206) {
switch_channel_t *channel = switch_core_session_get_channel(rtp_session->session);
const char *uuid = switch_channel_get_partner_uuid(channel);
@@ -5118,6 +5272,13 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp
return SWITCH_STATUS_FALSE;
}
if (rtp_session->fir_countdown) {
if (--rtp_session->fir_countdown == 0) {
send_fir(rtp_session);
//send_pli(rtp_session);
}
}
bytes = rtp_common_read(rtp_session, &frame->payload, &frame->flags, io_flags);
frame->data = RTP_BODY(rtp_session);
@@ -5311,6 +5472,45 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
}
}
if (switch_rtp_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) {
/* Normalize the timestamps to our own base by generating a made up starting point then adding the measured deltas to that base
so if the timestamps and ssrc of the source change, it will not break the other end's jitter bufffer / decoder etc *cough* CHROME *cough*
*/
if (!rtp_session->ts_norm.ts) {
rtp_session->ts_norm.ts = (uint32_t) rand() % 1000000 + 1;
}
if (!rtp_session->ts_norm.last_ssrc || send_msg->header.ssrc != rtp_session->ts_norm.last_ssrc) {
if (rtp_session->ts_norm.last_ssrc) {
rtp_session->ts_norm.m = 1;
if (rtp_session->ts_norm.delta) {
rtp_session->ts_norm.ts += rtp_session->ts_norm.delta;
}
}
rtp_session->ts_norm.last_ssrc = send_msg->header.ssrc;
rtp_session->ts_norm.last_frame = ntohl(send_msg->header.ts);
}
if (ntohl(send_msg->header.ts) != rtp_session->ts_norm.last_frame) {
rtp_session->ts_norm.delta = ntohl(send_msg->header.ts) - rtp_session->ts_norm.last_frame;
rtp_session->ts_norm.ts += rtp_session->ts_norm.delta;
}
rtp_session->ts_norm.last_frame = ntohl(send_msg->header.ts);
send_msg->header.ts = htonl(rtp_session->ts_norm.ts);
if (rtp_session->ts_norm.m) {
if (send_msg->header.m) {
rtp_session->ts_norm.m = 0;
} else {
send_msg->header.m = 1;
}
}
}
send_msg->header.ssrc = htonl(rtp_session->ssrc);
if (rtp_session->flags[SWITCH_RTP_FLAG_GOOGLEHACK] && rtp_session->send_msg.header.pt == 97) {
@@ -5447,6 +5647,8 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
send = 0;
}
if (send) {
send_msg->header.seq = htons(++rtp_session->seq);
@@ -5549,7 +5751,6 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
}
}
if (switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, (void *) send_msg, &bytes) != SWITCH_STATUS_SUCCESS) {
rtp_session->seq--;
ret = -1;